feat(provision): target registry + Cursor scanner (U10 U4) - #46
Conversation
U10 U2 (config-write engine opaque whole-file text format) merged (PR #45, fa9e4b2). START-HERE ▶ NEXT repointed to /unit-loop U3 or U4 (both parallel- eligible off merged U1); PRODUCT.md U10 row 1/7 → 2/7. No new decision fork (implementation unit; the byte-exact-noop + batch-guard learnings live in the compound doc; the 3 U10-wrap-up ledger rows wait for U7-complete).
Define verified project-scoped harness surfaces with fail-closed compatibility checks, and register a fail-soft user-scoped Cursor inventory scanner. Cover path containment, malformed configs, symlink handling, and scanner isolation.
📝 WalkthroughWalkthroughAdds a Cursor inventory scanner and registers it in ChangesCursor provisioning and inventory
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant scanAll
participant scanCursor
participant CursorFiles
participant MCPConfig
scanAll->>scanCursor: invoke Cursor scanner
scanCursor->>CursorFiles: read agents and skills
scanCursor->>MCPConfig: read mcp.json
CursorFiles-->>scanCursor: inventory items
MCPConfig-->>scanCursor: MCP server items
scanCursor-->>scanAll: combined Cursor inventory
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Adds Cursor to the inventory scan “spine” and introduces a provisioning target registry that encodes (as data) the verified project-scoped writable surfaces for Claude Code, Codex, and Cursor—supporting U10’s provisioning engine plan while preserving the existing fail-soft scanner behavior and contract stability.
Changes:
- Add a new Cursor scanner (
scanCursor) and register it as a single newSCANNERSrow. - Add a provisioning target registry + resolver + fail-closed compatibility checker for known harness surfaces.
- Expand tests to cover Cursor scanning and target compatibility cases; refresh roadmap/docs to reflect recent U10 progress.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/scan.test.ts | Adds unit coverage for the new Cursor scanner and scanAll roster behavior. |
| tests/provision-targets.test.ts | New tests for provisioning target registry resolution and compatibility failure modes. |
| src/scan/index.ts | Registers Cursor in the scanner registry and exports scanCursor. |
| src/scan/cursor.ts | Implements user-scoped Cursor inventory scanning for agents/skills/MCP. |
| src/provision/targets.ts | New registry + resolution + compatibility checks for project-scoped provisioning targets. |
| docs/START-HERE.md | Updates “next steps” narrative to reflect current unit sequencing. |
| docs/PRODUCT.md | Updates product status text for U10 progress (one inconsistency noted in review). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| **Still to build:** | ||
| - **U10 (building — 1 of 7 sub-units in) — project provisioning:** a project carries one versioned "blueprint" (which roles run in which harness, on which model, with which files), and agent-os pushes it into Claude Code, Codex, and Cursor natively — reversibly, with a dry-run preview and a drift report. First sub-unit shipped (PR #44): the typed manifest contract + a pure/total loader + the shared **front-gate** that certifies a blueprint (valid schema, no secrets, no machine-specific paths) before any provisioning verb runs. Rescoped from the earlier "parity actions" framing by lived dogfood evidence (decision #52). | ||
| - **U10 (building — 1 of 7 sub-units in) — project provisioning:** a project carries one versioned "blueprint" (which roles run in which harness, on which model, with which files), and agent-os pushes it into Claude Code, Codex, and Cursor natively — reversibly, with a dry-run preview and a drift report. Two sub-units shipped: the typed manifest contract + a pure/total loader + the shared **front-gate** that certifies a blueprint (valid schema, no secrets, no machine-specific paths) before any provisioning verb runs (PR #44), and the config-write engine's opaque whole-file `text` write primitive the copy/compose transforms need — verbatim, byte-identical, on the same backup/atomic-write/undo discipline as structured configs (PR #45). Rescoped from the earlier "parity actions" framing by lived dogfood evidence (decision #52). |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/provision/targets.ts (1)
203-238: 🩺 Stability & Availability | 🔵 TrivialFail-closed compatibility gate is sound; note the inherent TOCTOU gap to the eventual writer.
The ancestor symlink walk, directory-vs-file discrimination, and merge-content validation are all correctly fail-closed and well exercised by the paired test file. One architectural point worth flagging for the writer implementation that consumes this:
checkTargetCompatibilityand the actual write are necessarily two separate operations, so there's an inherent check-then-write race (another process/symlink swap between the check and the write) that this module alone cannot close. Since the module's docstring already scopes it to "checks the live path shape before any write begins," this isn't a defect here — just make sure the writer opens withO_NOFOLLOW/equivalent (or re-validates atomically) rather than trusting this check as a standalone guarantee at write time.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/provision/targets.ts` around lines 203 - 238, Update the writer that consumes checkTargetCompatibility to protect the actual open/write operation against path changes after validation. Open the destination with O_NOFOLLOW or an equivalent atomic revalidation, and do not rely on checkTargetCompatibility alone to prevent symlink or ancestor swaps; preserve the existing compatibility-check behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/PRODUCT.md`:
- Line 6: Advance the U10 roadmap references consistently for U4: in
docs/PRODUCT.md lines 6, 51, and 119, update the latest PR, progress count, and
description to reflect 3 of 7 completed with U4 included; in docs/START-HERE.md
line 61, change NEXT to identify the remaining unit(s) rather than U4.
---
Nitpick comments:
In `@src/provision/targets.ts`:
- Around line 203-238: Update the writer that consumes checkTargetCompatibility
to protect the actual open/write operation against path changes after
validation. Open the destination with O_NOFOLLOW or an equivalent atomic
revalidation, and do not rely on checkTargetCompatibility alone to prevent
symlink or ancestor swaps; preserve the existing compatibility-check behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 079e32a6-d5a0-4865-b15f-aebac418cdda
📒 Files selected for processing (7)
docs/PRODUCT.mddocs/START-HERE.mdsrc/provision/targets.tssrc/scan/cursor.tssrc/scan/index.tstests/provision-targets.test.tstests/scan.test.ts
| > **Freshness rule:** `/handoff` updates this page whenever something ships. If this page and reality ever disagree, that's a bug — flag it. | ||
|
|
||
| _Last updated: 2026-07-21 · Status: **v0.1 "Continuity" in progress — 11 of 15 units shipped**; latest: **U10 BUILDING** — the provisioning engine's first sub-unit (the manifest contract + blueprint loader + shared front-gate) shipped + merged (PR #44, decisions #53–#54). Next: **U10 sub-units U2–U4** (parallel-eligible). · Roadmap postures locked by the 2026-07-10 interview (decisions #32–#41)_ | ||
| _Last updated: 2026-07-21 · Status: **v0.1 "Continuity" in progress — 11 of 15 units shipped**; latest: **U10 BUILDING** — 2 of 7 provisioning sub-units merged: the manifest contract + loader + shared front-gate (PR #44, decisions #53–#54), and the config-write engine's opaque whole-file `text` write primitive (PR #45). Next: **U10 sub-units U3–U4** (parallel-eligible). · Roadmap postures locked by the 2026-07-10 interview (decisions #32–#41)_ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Advance the roadmap consistently for U4.
The target registry and Cursor scanner introduced by this PR make the current 2/7 checkpoint and U4 “NEXT” instruction stale after merge.
docs/PRODUCT.md#L6-L6: update the latest PR and U10 progress to reflect U4 and 3/7.docs/PRODUCT.md#L51-L51: change “1 of 7”/“two sub-units” to the new consistent count and description.docs/PRODUCT.md#L119-L119: update the decoder ring to the same progress.docs/START-HERE.md#L61-L61: point NEXT to the remaining unit(s), not U4 again.
📍 Affects 2 files
docs/PRODUCT.md#L6-L6(this comment)docs/PRODUCT.md#L51-L51docs/PRODUCT.md#L119-L119docs/START-HERE.md#L61-L61
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/PRODUCT.md` at line 6, Advance the U10 roadmap references consistently
for U4: in docs/PRODUCT.md lines 6, 51, and 119, update the latest PR, progress
count, and description to reflect 3 of 7 completed with U4 included; in
docs/START-HERE.md line 61, change NEXT to identify the remaining unit(s) rather
than U4.
Bots (Copilot + CodeRabbit) on PR #46/#47 caught two continuity-doc nits in main (not in the U3/U4 diffs): - PRODUCT.md:51 still read '1 of 7 sub-units in' — a leftover from the U2 handoff where the other two counts were updated to 2/7. Now consistent. - START-HERE ▶ NEXT gate note said parens 'command-substitute'; they actually glob-fail in zsh (backticks/$() command-substitute). Wording corrected. The U3/U4 CODE drew zero bot findings.
|
Bot review triaged — the U3/U4 code drew zero findings from either bot. All flagged items were continuity-doc nits in
No changes to this branch (the reviewed code is clean). Ready to merge. |
U10 U4 — Target registry + Cursor scanner row
Part of the U10 provisioning engine plan. Build-time harness knowledge as data, and the Observe side keeps pace: Cursor joins the scan spine (R9, R10, R13, R14; KTD4).
What changed
src/provision/targets.ts— oneTargetDescriptorper harness (Claude Code, Codex, Cursor): surface locations, formats, create-vs-merge shape, project-scope path resolution viaposix.join(R9).checkTargetCompatibilityis a pure function over injected io, fail-closed, mapping AE4's incompatible-state cases —file-where-directory,symlinktarget,malformed(unparseable merge parent) — with absent → compatible for create-shape. Error messages carry surface + path only, never file content. Codex skills intentionally excluded (issue U9 deferral: Codex skill discovery + verify skill roots holistically (.agents vs .claude vs .codex) #36 pointer).src/scan/cursor.ts+src/scan/index.ts— the Cursor scanner (user-scope~/.cursor, fail-soft per surface, follows thescanCodexshape) added as oneSCANNERSrow. TheRuntimeenum already includescursor— no contract change (one-row extensibility, R13/R14). Cursor agents represented via the existingpluginkind; a distinct kind is deferred to later contract work.Verification
bun test560 pass / 0 fail,tscclean.~/.cursorinstall (agents/*.md,skills/<name>/SKILL.md,mcp.json .mcpServers) — the plan's load-bearing execution note; independently re-validated by the reviewer.Provenance & review (dogfood: Codex-executes / Claude-reviews)
Built by Codex (
gpt-5.6-sol xhigh) viace-work(incl.ce-simplify-code+ce-code-review) in an isolated worktree, then reviewed cross-model by Claude as the architect gate. The cross-model adversarial pass ran during the build (host Codex → peer Claude,opus-4-8,independence_verified, 0 additional findings) — verified on disk. Adversarial hardening folded: fail-closed stat/read, symlinked-ancestor rejection, directory-at-target rejection, valid-vs-broken Cursor symlink handling.Deferred (tracked, not blockers)
lstatsemantics (outside U4); distinct Cursor-agent inventory kind + productionscanAllexposure → later contract/entry-point work; project-scope observation → U11 / issue U9 deferral: per-project inventory scope (mcp/skills/plugins + user-vs-project precedence) → U11 #35.🤖 Built by Codex, reviewed by Claude Code
Summary by CodeRabbit
New Features
Documentation