instar 1.3.477 → 1.3.479

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude/skills/autonomous/SKILL.md +10 -0
  2. package/.claude/skills/autonomous/hooks/autonomous-stop-hook.sh +418 -23
  3. package/.claude/skills/autonomous/scripts/setup-autonomous.sh +29 -0
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +46 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CartographerNavigator.d.ts +89 -0
  8. package/dist/core/CartographerNavigator.d.ts.map +1 -0
  9. package/dist/core/CartographerNavigator.js +354 -0
  10. package/dist/core/CartographerNavigator.js.map +1 -0
  11. package/dist/core/CartographerTree.d.ts +7 -0
  12. package/dist/core/CartographerTree.d.ts.map +1 -1
  13. package/dist/core/CartographerTree.js +9 -0
  14. package/dist/core/CartographerTree.js.map +1 -1
  15. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  16. package/dist/core/PostUpdateMigrator.js +44 -3
  17. package/dist/core/PostUpdateMigrator.js.map +1 -1
  18. package/dist/scaffold/templates.d.ts.map +1 -1
  19. package/dist/scaffold/templates.js +1 -0
  20. package/dist/scaffold/templates.js.map +1 -1
  21. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  22. package/dist/server/CapabilityIndex.js +1 -0
  23. package/dist/server/CapabilityIndex.js.map +1 -1
  24. package/dist/server/routes.d.ts.map +1 -1
  25. package/dist/server/routes.js +55 -0
  26. package/dist/server/routes.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/data/builtin-manifest.json +64 -64
  29. package/src/scaffold/templates.ts +1 -0
  30. package/upgrades/1.3.478.md +44 -0
  31. package/upgrades/1.3.479.md +53 -0
  32. package/upgrades/side-effects/autonomous-completion-real-checks.md +88 -0
  33. package/upgrades/side-effects/cartographer-subtree-nav.md +81 -0
@@ -0,0 +1,53 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Autonomous jobs can now declare an optional `verification_command` (with an optional
9
+ `verification_cwd`; setup also records `work_dir`). When the independent completion judge says a
10
+ goal is met — which it decides by reading what the agent *surfaced in the transcript*, not by
11
+ running anything — the autonomous Stop hook now RUNS that command and only lets the run stop if the
12
+ command ALSO passes (exit 0). Any failure, timeout, missing-timeout-binary, refused-destructive
13
+ command, or a tripped breaker → keep working with the command's output as next-turn guidance. It
14
+ can never CAUSE a premature exit (the safe direction). The command runs under a portable bounded
15
+ timeout (`timeout`/`gtimeout` with `-k`, else a perl process-group-kill, else "unavailable → keep
16
+ working"), in a scrubbed env (fixed PATH, no auth token), with its output scrubbed for secrets and
17
+ DATA-labeled so an echoed "all tests pass" can't launder into a later judge verdict, and a P19
18
+ breaker stops a stuck/flaky check from spinning the judge + command to the duration limit. Every
19
+ run appends one row to `logs/autonomous-realcheck.jsonl`. Off-switch:
20
+ `autonomousSessions.completionDiscipline.realCheck.enabled` (read at the hook chokepoint — no
21
+ restart). It is a NO-OP unless a job declares a `verification_command`.
22
+
23
+ ## What to Tell Your User
24
+
25
+ When I'm running on my own toward a goal, a second, independent check decides "is it really done?".
26
+ Until now that check only *read what I wrote* — so if I said the tests passed, it believed me, even
27
+ if I'd misread them or run them in the wrong place. Now, when a goal is checkable by a command (a
28
+ test suite, a build, a quick check), I can actually RUN that command before I'm allowed to stop — so
29
+ "done" means the check really passed, not just that I claimed it. If the check fails, I don't stop;
30
+ I keep working with the failure in front of me. It only ever makes me keep working longer, never
31
+ stop early, and it's off unless a job specifically asks for it. You don't have to set anything up;
32
+ it's there for the kinds of autonomous jobs that have a clear "run this to verify" command.
33
+
34
+ ## Summary of New Capabilities
35
+
36
+ - Autonomous jobs gain an opt-in real-check: `instar`'s autonomous setup takes
37
+ `--verification-command "<cmd>"` and `--verification-cwd "<dir>"`; a met verdict runs the command
38
+ and the run stops only if it passes.
39
+ - A new audit trail at `logs/autonomous-realcheck.jsonl` (command, cwd, exit, outcome per run).
40
+ - Config: `autonomousSessions.completionDiscipline.realCheck` (`enabled`, `timeoutMs`, `maxChars`,
41
+ `captureBytes`, `failBreakerThreshold`, `failWindowMs`, `failCooldownMs`) — read live, no restart.
42
+
43
+ ## Evidence
44
+
45
+ - Spec (converged, 3 review rounds, approved): `docs/specs/autonomous-completion-real-checks.md`;
46
+ convergence report `docs/specs/reports/autonomous-completion-real-checks-convergence.md`.
47
+ - Tests, all green: 24 unit (`tests/unit/autonomous-stop-hook-realcheck.test.ts`), 4 integration
48
+ (`tests/integration/autonomous-realcheck-setup-roundtrip.test.ts`), 2 e2e
49
+ (`tests/e2e/autonomous-realcheck-verification-lifecycle.test.ts` — the "feature is alive" test
50
+ proving the gate is wired into the real production met-path). The cardinal invariant (no
51
+ verification problem can cause a premature exit) is independently second-pass reviewed and
52
+ traced path-by-path.
53
+ - Side-effects review: `upgrades/side-effects/autonomous-completion-real-checks.md`.
@@ -0,0 +1,88 @@
1
+ # Side-Effects Review — Autonomous completion: real-checks verification
2
+
3
+ **Version / slug:** `autonomous-completion-real-checks`
4
+ **Date:** `2026-06-10`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `echo (Phase 5 — REQUIRED: touches the autonomous Stop-hook continue/stop authority + a new gate)`
7
+
8
+ ## Summary of the change
9
+
10
+ Autonomous jobs gain an OPT-IN `verification_command` (+ optional `verification_cwd`; setup also records `work_dir`). When the transcript-judge (`CompletionEvaluator`, via `POST /autonomous/evaluate-completion`) returns `met:true`, the autonomous Stop hook (`autonomous-stop-hook.sh`) now RUNS the declared command and only allows the session to exit if the command ALSO passes (exit 0). Any failure mode — non-zero, timeout, missing-timeout-binary, refused-destructive, or breaker-open — routes to KEEP WORKING (the safe direction), surfacing the command's sanitized output as next-turn guidance. The judge stays transcript-only and unchanged; the real check is a second, independent, deterministic gate layered on the (rare) met path. Files: `.claude/skills/autonomous/hooks/autonomous-stop-hook.sh` (the gate `realcheck_gate`, `run_verification`, P19 breaker helpers, audit, config-read), `.claude/skills/autonomous/scripts/setup-autonomous.sh` (new flags + state fields), `src/config/ConfigDefaults.ts` (the `realCheck` config block nested in `completionDiscipline`), `src/core/PostUpdateMigrator.ts` (3 marker bumps to `REALCHECK_VERIFY` + a `migrateClaudeMd` appended subsection), `src/scaffold/templates.ts` (`generateClaudeMd`), `.claude/skills/autonomous/SKILL.md` (Write-template docs), + unit/integration/e2e tests. Spec: `docs/specs/autonomous-completion-real-checks.md` (converged, approved).
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `autonomous Stop-hook EXIT decision (met path)` — **modify** — a met:true verdict no longer auto-exits; it now ALSO requires the declared `verification_command` to pass (exit 0). The modification is purely additive in the SAFE direction: it can only WITHHOLD an exit, never CAUSE one.
15
+ - `realcheck_gate` — **add** — the new gate function; returns 0 (allow exit) ONLY on disabled / no-command / breaker-closed-PASS; returns 1 (keep working) on every failure mode.
16
+ - `realcheck breaker (CD_BACKOFF_STATE)` — **add** — a P19 backoff+breaker+cap sibling counter that short-circuits a stuck/flaky command (no judge re-fire, no command run) and raises ONE Attention item.
17
+ - `destructive-pattern pre-block` — **add** — a coarse literal-shape guard refusing high-signal destructive commands before execution (→ keep working).
18
+
19
+ ---
20
+
21
+ ## 1. Over-block
22
+
23
+ **What legitimate inputs does this change reject that it shouldn't?**
24
+
25
+ The gate blocks the autonomous EXIT, not a user message. Its only "over-block" is keeping the agent working when the goal is actually done — which happens only if a declared `verification_command` falsely FAILS (a flaky check, a wrong CWD, a stale-artifact premise). Concrete: a job declares `verification_command: "npm test"` but the build lives in a worktree the job forgot to point at via `verification_cwd` → `npm test` from `work_dir` fails → the agent keeps working past a genuine completion. Mitigations: (a) the failure output is fed back as next-turn guidance framed as "the check may be wrong/mis-scoped — say so" (P13 / A-Wall-Is-a-Hypothesis), so the agent can correct the premise rather than grind; (b) the P19 breaker stops a persistently-failing check from spinning to duration and raises an Attention item so the operator sees the bad command; (c) the duration limit is the hard backstop; (d) the whole feature is a NO-OP unless a job declares the command, and is opt-in per job. Critically, over-block here is bounded + surfaced + recoverable — it can never cause the dangerous direction (a premature exit).
26
+
27
+ ---
28
+
29
+ ## 2. Under-block
30
+
31
+ **What failure modes does this still miss?**
32
+
33
+ A `verification_command` the agent constructs to falsely PASS: `verification_command: "true"`, `"npm test || true"`, a `test -f <stale-flag>` the agent `touch`ed earlier, or a PATH-shadowed `npm`. These are honestly named residuals (spec §6.2): the feature strengthens against HONEST failure (misread output, stale tree, premature "done"), not against an adversarial agent — which already holds far larger powers (edit source, push). The floor never drops below today (the independent judge still had to say met). The defeat is made DETECTABLE post-hoc via the audit row (`logs/autonomous-realcheck.jsonl` records the command + cwd + exit), not prevented. The conversational/transcript path is unchanged — this only adds a gate on the autonomous met path.
34
+
35
+ ---
36
+
37
+ ## 3. Level-of-abstraction fit
38
+
39
+ **Is this at the right layer?**
40
+
41
+ Yes. The real check is a deterministic STRUCTURAL VALIDATOR (an exit-code — `signal-vs-authority.md`'s allowed detector class), layered as a corroborator on top of the existing full-context LLM judge (`CompletionEvaluator`) which remains the primary JUDGMENT authority on the met verdict. The check runs in the Stop hook (the correct layer — it owns the continue/stop decision), reuses the existing `CD_BACKOFF_STATE` breaker machinery, the `hb_sanitize`/`hb_leak_hit` output discipline, and the `cd_raise_attention_item` notification primitive rather than re-implementing them. It does NOT add a parallel gate or a new authority — it feeds the existing continue/stop decision.
42
+
43
+ ---
44
+
45
+ ## 4. Signal vs authority compliance
46
+
47
+ **Does this hold blocking authority with brittle logic, or produce a signal that feeds a smart gate?**
48
+
49
+ Compliant. Per `docs/signal-vs-authority.md`: an exit-code is a structural validator (the doc's explicitly-allowed detector class — "this type-checks, this length is bounded"), not a meaning-judgment. The LLM judge remains the sole *judgment* authority that must independently say met; the real check's only autonomous authority is in the SAFE (keep-working) direction — a brittle check that errs toward "keep working" (bounded by duration) is NOT the dangerous "brittle authority that blocks a legitimate action" the principle forbids. It is a corroborator that RAISES the bar for stopping, never one that forces a premature stop. Every error/ambiguity/timeout path resolves to keep-working.
50
+
51
+ ---
52
+
53
+ ## 5. Interactions
54
+
55
+ **Does it shadow another check, get shadowed, double-fire, race?**
56
+
57
+ - **CD_BLOCK_TERMINAL / contradictory hard-blocker:** the gate sits INSIDE the existing `if [[ "$EVAL_MET" == "true" ]]` block, AFTER the `CD_BLOCK_TERMINAL` guard + the P13 check — so a turn emitting BOTH a `<hard-blocker>` and a met-condition short-circuits before the gate (tested). The gate never runs on a hard-blocker/P13-blocked turn.
58
+ - **Native /goal mode:** the `goal_mode:native` branch returns far earlier (line ~452) — the gate is unreachable there; native runs are unaffected.
59
+ - **P19 breaker vs judge breaker:** a SIBLING counter in the same `CD_BACKOFF_STATE` sidecar (atomic `.tmp.$$`+mv writes, fails CLOSED=keep-verifying on a corrupt sidecar) — does not collide with the judge breaker.
60
+ - **Idle-backoff:** a met→fail iteration is by definition not a rapid-idle one, so the backoff self-clamp is unaffected; the verification timeout (≤120s) + judge curl (≤35s) stay far under the ~10000s registered Stop-hook timeout (no host-kill / fail-open-strand risk).
61
+ - **Adjacent (out of scope, captured separately):** the feature's integration test surfaced a PRE-EXISTING latent bug in `setup-autonomous.sh`'s multi-session start-gate — when run with `--report-topic`, no server reachable, AND `.instar/autonomous/` empty, the local-count fallback `ls …/*.local.md | grep -c…` exits non-zero on an empty glob and trips `set -euo pipefail`, aborting before the state write. NOT part of this feature; not fixed here (no-batching rule); recorded for a separate follow-up fix (`grep -c … || true`).
62
+
63
+ ---
64
+
65
+ ## 6. External surfaces
66
+
67
+ **Does it change anything visible to other agents, users, other systems?**
68
+
69
+ - A new audit file `logs/autonomous-realcheck.jsonl` (read-only, size-rotated). No new API route.
70
+ - One new Attention item source (`autonomous-realcheck-stuck`) when the breaker trips — deduped per run (Bounded-Notification-Surface compliant).
71
+ - Next-turn guidance gains the real-check output, sanitized (control-strip → UTF-8 scrub → leak-scrub incl. the agent's own authToken + `Bearer` → clamp) and explicitly DATA-labeled so an echoed "all tests pass" cannot launder into a later judge verdict.
72
+ - Runtime dependency: it RUNS a command unattended in the Stop hook — bounded by a portable timeout ladder (`timeout`/`gtimeout` with `-k`, else a perl `setpgrp` group-kill, else unavailable→keep-working), scrubbed env (fixed PATH, no authToken, no `npm_config_*`/`NODE_OPTIONS`), and a destructive-pattern pre-block. Timing depends on the declared command, bounded by `realCheckTimeoutMs` (default 120s) and only on the rare met path.
73
+
74
+ ---
75
+
76
+ ## 7. Rollback cost
77
+
78
+ **If this turns out wrong in production, what's the back-out?**
79
+
80
+ Cheap and instant. `autonomousSessions.completionDiscipline.realCheck.enabled: false` in `.instar/config.json` is read at the hook chokepoint each fire (no restart) and reverts to transcript-only behavior. A job simply omitting `verification_command` is already unaffected (byte-identical to today — tested). No data migration, no state repair. The migrator marker bump (`REALCHECK_VERIFY`) is idempotent; a customized hook is left untouched. Worst case (the gate misbehaves for a job that opted in) is bounded by the duration limit and surfaced via the audit + Attention item.
81
+
82
+ ---
83
+
84
+ ## Second-pass review (Phase 5)
85
+
86
+ **Reviewer: echo (independent pass) — Concur with the review.**
87
+
88
+ Independently traced every path through `realcheck_gate` (hook ~1095-1121) and `run_verification` (~929-1064): the cardinal invariant holds — `realcheck_gate` returns 0 (allow exit) ONLY on `RC_ENABLED != 1`, empty `VERIFICATION_COMMAND`, or `RC_OUTCOME == "pass"`; every other outcome (fail, 124 timeout, 127 unavailable, 126 refused-destructive, breaker-open, corrupt sidecar) returns 1 (keep working). All three completion-met `exit 0` sites are strictly inside `if realcheck_gate; then`; the non-completion exits (hard-blocker, emergency-stop, corrupt-state fail-safe) are correctly NOT wrapped. Breaker fail-direction verified empirically (corrupt `CD_BACKOFF_STATE` → fails=0 < threshold → echo 0 → CLOSED → check still runs — fail-CLOSED/safe). Perl timeout wrapper semantics verified live (exit-1→FAIL, exit-0→PASS, sleep-3-under-1s→124 in ~1s, no orphan). Signal-vs-authority posture legitimate (structural-validator corroborator, safe-direction-only authority, LLM judge unchanged and still primary). 24 unit + 4 integration + 2 e2e green. One under-stated nuance (a condition-path fail + same-turn legacy-promise match could run the command twice in one fire) is bounded, non-harmful (same breaker, neither can cause a premature exit), and does not affect the invariant.
@@ -0,0 +1,81 @@
1
+ # Side-Effects Review — Cartographer Subtree Navigation (spec #5, Tier 2)
2
+
3
+ **Version / slug:** `cartographer-subtree-nav`
4
+ **Date:** `2026-06-10`
5
+ **Author:** `Echo`
6
+ **Spec:** `docs/specs/CARTOGRAPHER-SUBTREE-NAV.md` (converged 1 round + a focused buildability review, approved)
7
+ **Second-pass reviewer:** `not required — convergence pinned the collapse rule, the two-phase scoring, batched fresh, and the migrator-only classification; this review covers the seven dimensions on the as-built deterministic code`
8
+
9
+ ## Summary of the change
10
+
11
+ The capstone of cartographer-conformance: a **deterministic recursive navigator** over
12
+ the doc-tree. Given a query, it walks the tree's summaries top-down (a bounded frontier,
13
+ not all N nodes), scores nodes by relevance, and returns the **minimal relevant
14
+ subtree** — the paths a sub-agent should be scoped to instead of the whole repo.
15
+ `GET /cartographer/navigate`. Observe-only, deterministic-first; an optional LLM re-rank
16
+ is a dark structural stub. Dark behind `cartographer.enabled`.
17
+
18
+ ## Files touched
19
+
20
+ - NEW `src/core/CartographerNavigator.ts` (scoring + the bounded recursive walk + collapse + sanitization).
21
+ - MODIFIED (additive): `src/core/CartographerTree.ts` (one public `currentOidMap()` accessor exposing the existing batched `currentOids()` — for batched `fresh`), `src/config/ConfigDefaults.ts` (`cartographer.subtreeNav`), `src/server/routes.ts` (the navigate route), `src/server/CapabilityIndex.ts`, `src/core/PostUpdateMigrator.ts` (CLAUDE.md section), `tests/unit/feature-delivery-completeness.test.ts` (legacy-migrator allowlist entry).
22
+ - TESTS: 32 across 3 tiers.
23
+
24
+ ## 1. Over-block
25
+
26
+ The navigator blocks nothing (observe-only — it returns a suggestion). No gate.
27
+
28
+ ## 2. Under-block / correctness
29
+
30
+ A bounded walk could MISS a relevant deep node if an intermediate dir's provisional
31
+ score gates it out. The build resolved this (a documented decision): the provisional
32
+ dir score peeks at descendant path BASENAMES to a bounded depth (PEEK_DEPTH=2, path-only,
33
+ non-recursive in score — no deadlock), so the spec's own example ("relevant code under
34
+ `src/messaging/`") and the "never-swept tree navigates on path signal" requirement hold.
35
+ A dir never enters `relevantPaths` on a single descendant's strength — only via the
36
+ collapse rule (≥0.6 of VISITED children relevant). `summaryCoverage` is reported so a
37
+ caller knows how much ranking was summary-informed vs path-only (honest on a never-swept
38
+ tree).
39
+
40
+ ## 3. Level-of-abstraction fit
41
+
42
+ Pure scorer + pure walk in `CartographerNavigator`; the route is a thin read surface;
43
+ the tree exposes one new read accessor. No layer reaches across; the navigator takes the
44
+ tree + query and returns a manifest. Fully unit-testable on a fixture tree.
45
+
46
+ ## 4. Determinism / cost (the cartographer-project footgun this avoids)
47
+
48
+ The shipped value is 100% deterministic — local index/summary reads only; zero token
49
+ cost, zero egress, byte-identical run-to-run. The bounded frontier (top-`branchingFactor`
50
+ children to `maxDepth`, capped by `maxNodesVisited`/`maxResults`) means cost is
51
+ O(frontier), not O(tree); `fresh` is one batched `git ls-tree`, not per-node. The LLM
52
+ re-rank ships OFF (Signal vs. Authority — the deterministic score is the authority).
53
+
54
+ ## 5. Security / data-egress
55
+
56
+ - **Zero egress** in the default config (deterministic core). The optional LLM re-rank
57
+ inherits spec #2's posture (off-Claude probe, separate egress-ack) and ships OFF.
58
+ - **Summaries are untrusted on output (the hard safety contract):** every emitted summary
59
+ passes `neutralizeInstructionShapedContent` then `delimitUntrusted` — so a summary that
60
+ smuggled "ignore your instructions" reaches the downstream sub-agent as quoted,
61
+ declawed data, never an instruction. (A Tier-1 test asserts an instruction-shaped
62
+ summary is emitted as `[neutralized: …]`.) The route consumes NO path input (paths are
63
+ produced), so there is no traversal surface; `query` length + numeric bounds are
64
+ validated (400 on violation).
65
+
66
+ ## 6. Failure modes / load
67
+
68
+ No poller, no background work — the navigate is a synchronous read per request, bounded.
69
+ Empty query short-circuits. A never-swept tree degrades gracefully to path navigation.
70
+ No load impact.
71
+
72
+ ## 7. Migration / compatibility (Migration Parity)
73
+
74
+ `cartographer.subtreeNav` nests under `cartographer` (deep-merge backfill — no
75
+ migrateConfig). The CLAUDE.md section ships via `migrateClaudeMd` (own marker 'Scope a
76
+ sub-agent to a subtree', idempotent) and is registered in the feature-completeness test's
77
+ `legacyMigratorSections` allowlist — EXACTLY as specs #1/#2/#3's cartographer sections
78
+ (migrator-only, not `generateClaudeMd`/shadow; verified at convergence). The route is in
79
+ CapabilityIndex. The `currentOidMap()` addition to CartographerTree is purely additive
80
+ (exposes an existing private read). Rollback: disabling `cartographer.enabled` 503s the
81
+ route. No migration reversal.