Commit Graph
6 Commits
Author SHA1 Message Date
james.maesandClaude Opus 4.7 508cf924d0 docs(packages): per-package README files
Adds README.md to each of the 13 SPM packages (AgentCore, Bus, Config,
DevOverlay, Harness, Keychain, Logging, MCP, Memory, Replay, Shell, Vision,
Voice). Each covers purpose, key public types, deps, consumers, invariants
(pulled from CLAUDE.md + grep-gates + audit findings), test stack, and
notable files. Memory README explicitly marks the package functionally OFF
until vec0.dylib + Ollama models land.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 17:13:33 -05:00
james.maes 0785d6e57d fix(01-WR-11): typed FeatureFlag enum prevents silent-typo feature disable
Phase 1 REVIEW.md WR-11: `FeatureFlags.isEnabled(_ key: String)` fell
through to `false` on any typo — `"orpheusTtsEnabled"` (wrong case),
`"orpheus_tts_enabled"` (wrong separator), etc. Phase 6 (Orpheus /
WhisperKit) wiring depends on these flags; a silently-disabled
feature caused by a typo is nearly impossible to debug.

packages/Config/Sources/Config/FeatureFlags.swift
- Add `public enum FeatureFlag: String, CaseIterable, Sendable` with
  cases `orpheusTTSEnabled`, `whisperKitSTTEnabled` (both known keys
  per REQUIREMENTS.md).
- Add `isEnabled(_ flag: FeatureFlag)` as the canonical typed path.
- Rename the string-keyed lookup to `isEnabledDynamic(_:)` so
  production callers get a compile error on typos — the dynamic
  string path is retained only for the dev overlay's "list all
  flags" affordance.

packages/Config/Tests/ConfigTests/PerTurnSnapshotTests.swift
- Update two existing tests to use the typed-enum API.
- New `test_featureFlagEnumRawValueMatchesDecoder` — regression guard
  that the enum cases' rawValue matches the JSON key the decoder
  sees, so a rename to `orpheusTtsEnabled` fails the build, not
  silently breaks feature detection.

No production callers of the old string-keyed `isEnabled` exist
outside tests — no migration needed elsewhere.
2026-04-23 16:29:54 -05:00
james.maes 569bc80451 fix(01-WR-04): disambiguate SchemaMigrator error payloads
Phase 1 REVIEW.md WR-04: `ConfigError.futureSchema(version:)` and
`ConfigError.unknownSchemaVersion(Int)` both carried a single Int
whose meaning depended on context — `futureSchema(2)` when migrating
`from: 2, to: 1` reports "2" but users read it as "your target is 2"
rather than "you have v2, this build only supports v1". For
multi-step migrations, `unknownSchemaVersion` also reported an
intermediate version, not the user's file version.

packages/Config/Sources/Config/ConfigError.swift
- `futureSchema(have:supports:)`: `have` is the user's version,
  `supports` is `SchemaMigrator.currentVersion`.
- `unknownSchemaVersion(have:supports:)`: `have` is the intermediate
  source version at the failing step, `supports` is the migration
  target. Callers can report "config is at v3, Jarvis supports up to
  v2" unambiguously.

packages/Config/Sources/Config/SchemaMigrator.swift
- Propagate `to:` through `migrateStep` so the thrown
  `unknownSchemaVersion` carries both numbers.

packages/Config/Tests/ConfigTests/SchemaMigratorTests.swift
- Update both negative-path assertions to the new enum shape.
2026-04-23 16:18:41 -05:00
james.maes e3024cdae3 fix(01-WR-03): DNS-rebind-safe Ollama host validation
Phase 1 REVIEW.md WR-03 (AGENT-05): `OllamaConfig.validateHost` only
string-matched the URL host against `{127.0.0.1, localhost, ::1}` — a
hijacked `/etc/hosts` or resolver that points `localhost` to a
non-loopback IP would pass validation, violating AGENT-05's "local
only" intent. IPv6 bracket handling (`[::1]`) was also inconsistent
across macOS versions.

packages/Config/Sources/Config/OllamaConfig.swift
- Normalize IPv6-bracketed hosts (`[::1]` → `::1`) before the string
  allowlist check.
- For IP literals (127.0.0.1, ::1), skip resolution — loopback by
  construction.
- For `localhost`, run `getaddrinfo` with AF_UNSPEC + AI_ADDRCONFIG
  and assert every resolved address is loopback:
    * IPv4: top octet == 0x7f (127.0.0.0/8)
    * IPv6: 15 zero bytes followed by 0x01 (::1)
- Fail closed on `getaddrinfo` errors or unknown address families.

Existing tests still pass (15/15) — no test changes needed because
`127.0.0.1` short-circuits the getaddrinfo path and the existing
config fixtures all use IP literals, not localhost.
2026-04-23 16:16:55 -05:00
james.maesandClaude Opus 4.7 1b2f067376 feat(01-02): build Config package (AGENT-05, SEC-05, SEC-08, OBS-05)
- Split config into LaunchSnapshot (frozen security keys: ollama,
  applescript, toolBlocklist, confirmationPolicy, logging) and
  PerTurnSnapshot (mutable: provider, tts, stt, featureFlags) per SEC-05
- OllamaConfig.init(from:) rejects non-localhost hosts at decode time
  with ConfigError.invalidOllamaHost (AGENT-05)
- AppleScriptPolicy has no skipAllowlist/bypass/regex field (SEC-08);
  reflection test ConfigSplitTests.test_noSkipAllowlistKey enforces
- FeatureFlags lives in PerTurnSnapshot only (OBS-05); reflection test
  LaunchSnapshotTests.test_featureFlagsNotInLaunchSnapshot enforces
- SchemaMigrator: currentVersion=1, v1->v1 pass-through, future
  versions throw ConfigError.futureSchema
- ConfigLoader.loadSnapshots: peek schemaVersion, migrate, decode both
  snapshots; wraps DecodingError into ConfigError.malformed
- ConfigStore actor holds launch + streams perTurn updates (file-
  watcher wiring is Plan 03 scope)
- Bundled default-config.json resource
- Tests: 15/15 pass covering all behaviors listed in the plan
- Deletes Plan 01 placeholders

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:19:41 -05:00
james.maes d8617ffe01 feat(01-01): add four SPM packages with Swift 6 strict concurrency
- packages/Keychain — zero SPM deps (Security.framework at link time only)
- packages/Logging — depends on apple/swift-log 1.5.3+; library product is
  named JarvisLogging to avoid collision with swift-log's own Logging module
- packages/Config — depends on Keychain + Logging (product JarvisLogging)
- packages/Shell — depends on Config + Logging; links AppKit,
  ServiceManagement, IOKit, Carbon for hotkey/launch-at-login surfaces

Every target (main + test) opts into .swiftLanguageMode(.v6) per D-04 so
data-race errors are compile-time failures, not warnings.

Placeholder sources (one per package) plus one trivial XCTest per package
per D-03 so each package builds standalone and has a passing test. Real
sources land in Plan 02 (Keychain/Config/Logging) and Plan 04 (Shell).

Bus/LLM/MCP/Voice/Memory packages NOT pre-created per D-01 — they arrive
in their owning phases (P2/P4/P5/P6/P7) to keep rebuild scope tight.
2026-04-22 12:21:07 -05:00