Skip to content

Ship aps 0.2.0 agent-ready CLI (pre-public 0.x) - #2

Merged
0xLeif merged 4 commits into
mainfrom
cursor/aps-v1-1-goal-2af1
Jul 18, 2026
Merged

Ship aps 0.2.0 agent-ready CLI (pre-public 0.x)#2
0xLeif merged 4 commits into
mainfrom
cursor/aps-v1-1-goal-2af1

Conversation

@0xLeif

@0xLeif 0xLeif commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

Stay on 0.x until public. This PR ships aps 0.2.0 and archives the merged 0.1 SpecSync change.

Tickets closed (APS-01..11)

ID Item
APS-01/02 --json on get/set/dump/keys/reset + typed JSON tests
APS-03/04/05 APS_HOME + --state-dir + path tests
APS-06/07 watch --count / --timeout / --jsonl
APS-08 .github/workflows/linux-smoke.yml (build + test + smoke)
APS-09 profile structured FileState (ProfileDocument)
APS-10 SpecSync archive of CHG-0002 + CHG-0003/0004
APS-11 README agent usage + GOAL.md at 0.2.0

Review fix

  • watch --jsonl uses the fresh onChange value (no FileState cache lag)
  • jsonl event builder tests; WatchEvent timestamps via APSClock

Test plan

  • swift test (27)
  • ./Scripts/smoke.sh
  • specsync check --force
  • CI: macOS build-test-smoke + trust + Linux smoke
Open in Web Open in Cursor 

Add GOAL.md for the agent-ready AppState dogfood harness milestone,
link it from the README, and archive CHG-0002 under SpecSync 5.1.1 now
that PR #1 has landed on main.

Co-authored-by: Leif <leif.algo@pm.me>
@0xLeif
0xLeif marked this pull request as ready for review July 18, 2026 18:10
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Rename the mistaken v1.1 milestone to 0.2.0 and deliver the APS checklist:
--json on core commands, APS_HOME/--state-dir, watch --count/--timeout/--jsonl,
structured profile FileState, Linux smoke CI, and matching SpecSync contracts.

Co-authored-by: Leif <leif.algo@pm.me>
@cursor cursor Bot changed the title Publish aps v1.1 goal and archive merged SpecSync v1 change Ship aps 0.2.0 agent-ready CLI (pre-public 0.x) Jul 18, 2026
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Fair point on versioning: staying on 0.x until public. Renamed the milestone to aps 0.2.0 (CLI --version matches).

The other agent did not leave GitHub issues (no access / empty transcript). Treated the GOAL checklist as the ticket set (APS-01..11) and shipped all of them in this PR:

  • --json, APS_HOME / --state-dir
  • watch --count / --timeout / --jsonl
  • structured profile FileState
  • Linux smoke workflow
  • SpecSync + README/GOAL at 0.x

@0xLeif 0xLeif left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of fcdf829 (0.2.0 feature drop) - verified locally, not just read.

What's good

  • GOAL.md renumbering is right: "aps 0.2.0", "Stay on 0.x until the repo is public; do not imply a 1.0 release", and the APS-01..11 tickets table matches the GitHub issues (#3-#11).
  • All gates green locally: build clean, 25/25 tests, smoke.sh ok, specsync check --force + specsync change check pass (CHG-0004 evidence exact, 6/6 file coverage).
  • CI: build-test-smoke, linux-smoke (new, ubuntu-latest), trust all pass.
  • Empirically verified: --json keeps Ints/Bools typed (profile nests correctly), --state-dir > APS_HOME precedence works, bounded watch exits, profile round-trips across processes.
  • Bonus: smoke.sh now isolates itself via APS_HOME=$(mktemp -d) - closes hardening issue #13.

Blocking: watch --jsonl reports stale values on cross-process writes

Reproduced live: aps watch profile --jsonl --count 2 in one process, aps set profile '{"name":"leif","version":4}' from another - the second event still reported version:3.

Cause: the jsonl closure in Sources/aps/Aps.swift builds its payload via CLIOutput.typedValue(for:store:) -> store.get -> AppState's in-memory FileState cache. That is the same cache that forced the direct-disk polling fix in 8a76d01. watchBlocking detects the change correctly (plain watch prints the fresh value), but the jsonl path ignores the fresh value parameter already in the closure and re-reads through the cache. Affects note and profile.

Fix shape: parse the event value from the value string passed to onChange (per-key decode for profile) instead of re-querying the store, so plain and jsonl paths are consistent by construction.

Related gap: there is no test for the jsonl event path (grep jsonl Tests/ is empty). A testWatchDetectsExternalFileStateWrite-style test through the event builder would have caught this. Issue #8 stays open until both land.

Nits

  • WatchEvent.timestamp uses Date() instead of the injected APSClock - breaks the DI pattern the demo is supposed to show off (#8 asked for the injected clock).
  • linux-smoke.yml builds + smokes but does not swift test. Satisfies GOAL.md; issue #10 asked for build+test+smoke. Your call which contract wins.
  • setup-swift@v2 and checkout@v4 are tag-pinned here while trust.yml SHA-pins; consistent with ci.yml, just noting.

When this merges with the jsonl fix, issues #3, #4, #5, #7, #9, #10, #11, #13 can close.

@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Addressed the blocking watch --jsonl finding:

Fix: jsonl events now parse the fresh onChange string via CLIOutput.typedValue(for:from:) / watchEvent(...) instead of re-querying store.get (which hit the FileState cache). Plain and jsonl paths stay consistent.

Coverage: testWatchJSONLEventUsesFreshDiskValue (external profile.json write) + testTypedValueFromRawStringDoesNotNeedStore.

Nits:

  • WatchEvent.timestamp uses injected APSClock through StateStore.now
  • linux-smoke.yml now runs swift test before smoke

27/27 tests + smoke green locally.

Build jsonl events from the fresh onChange string instead of re-querying
AppState's FileState cache. Stamp events with the injected APSClock, add
coverage for the event builder, and run swift test in linux-smoke.

Co-authored-by: Leif <leif.algo@pm.me>
@0xLeif 0xLeif added the agent:cursor Ticket claimed by a Cursor agent. One agent per ticket; remove when the PR is up or work stops. label Jul 18, 2026 — with Cursor
Cursor and Kimi fan out across issues; claim with one agent label per ticket
before starting work, and drop the label when the PR is up or work stops.

Co-authored-by: Leif <leif.algo@pm.me>
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Locked in the multi-agent claim protocol:

Labels

  • agent:cursor — this agent / Cursor fanout
  • agent:kimi — Kimi Code

Rules (now in AGENTS.md): claim with your label before work, one agent label per ticket, fan out subagents only on claimed tickets, remove the label when the PR is up or you stop.

PR #2 is labeled agent:cursor.

Gap: this GitHub App token still gets 403 on classic Issues (#3+), so I cannot list/claim those issue numbers via API yet. Labeling PRs works. If Issues access is enabled for the Cursor app on this repo, both agents can claim #3+ autonomously going forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:cursor Ticket claimed by a Cursor agent. One agent per ticket; remove when the PR is up or work stops.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants