session-orchestrator 5.11.0 → 5.12.0

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 (45) hide show
  1. package/.claude-plugin/marketplace.json +12 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.cursor-plugin/plugin.json +1 -1
  5. package/CHANGELOG.md +19 -0
  6. package/README.md +22 -12
  7. package/commands/session.md +3 -1
  8. package/docs/install.md +12 -8
  9. package/docs/session-config-reference.md +6 -6
  10. package/docs/session-config-template.md +2 -2
  11. package/hooks/hooks-codex.json +1 -1
  12. package/hooks/hooks.json +1 -1
  13. package/hooks/on-session-start.mjs +19 -10
  14. package/package.json +1 -2
  15. package/scripts/fleet-checkin.mjs +61 -3
  16. package/scripts/lib/config/remote-hosts.mjs +2 -2
  17. package/scripts/lib/config.mjs +1 -1
  18. package/scripts/lib/fleet-protocol.mjs +17 -0
  19. package/scripts/lib/session-end/vault-orphans.mjs +205 -0
  20. package/scripts/lib/session-invocation.mjs +14 -3
  21. package/scripts/lib/session-registry.mjs +14 -4
  22. package/scripts/lib/so-hud/collect.mjs +130 -0
  23. package/scripts/lib/so-hud/runtime.mjs +76 -0
  24. package/scripts/lib/state-md/idle-reset.mjs +239 -0
  25. package/scripts/lib/state-md/recommendations.mjs +26 -4
  26. package/scripts/lib/vault-mirror/namespace.mjs +3 -2
  27. package/scripts/lib/vault-mirror/process.mjs +143 -40
  28. package/scripts/lib/vault-mirror/render-learnings.mjs +6 -5
  29. package/scripts/lib/vault-mirror/utils.mjs +27 -13
  30. package/scripts/lib/vault-status/board-writer.mjs +32 -4
  31. package/scripts/resolve-session-invocation.mjs +64 -8
  32. package/scripts/so-hud.mjs +45 -0
  33. package/scripts/state-md-idle-reset.mjs +81 -0
  34. package/scripts/vault-orphans.mjs +171 -0
  35. package/skills/_shared/fleet-protocol.md +24 -2
  36. package/skills/_shared/state-ownership.md +3 -3
  37. package/skills/autopilot/SKILL.md +3 -2
  38. package/skills/session-end/SKILL.md +3 -2
  39. package/skills/session-end/references/phase-3-7e-vault-orphans.md +63 -0
  40. package/skills/session-end/references/phase-3-documentation-updates.md +11 -1
  41. package/skills/session-end/references/session-summary-template.md +4 -0
  42. package/skills/session-start/SKILL.md +1 -1
  43. package/skills/session-start/phase-7-5-mode-selector.md +3 -1
  44. package/skills/session-start/references/phase-1-5-session-continuity.md +12 -4
  45. package/AGENTS.md +0 -207
@@ -145,7 +145,7 @@ discipline as `createSpiralCarryoverIssue`).
145
145
 
146
146
  ## Phase 3: Documentation Updates
147
147
 
148
- > Always runs. Refreshes the session-lock heartbeat at entry (`updateHeartbeat`, #590-3 — skip when `persistence: false`) so a long close-out cannot lapse the 4h TTL, then walks 3.0 Defensive Cleanup → 3.1 SSOT files → 3.2 Docs Verification → 3.2a Session Handover → 3.3 Claude-rules freshness → 3.4/3.4a STATE.md write + coordinator-snapshot cleanup → 3.45 Telemetry Flush → 3.5/3.5a/3.6.x session memory, learning extraction and the mechanical skip-plan tail → 3.7/3.7a/3.7b/3.7c/3.7d metrics write, recommendations, durable commit (#490), vault board → closed, session-eval. Full procedure: [`references/phase-3-documentation-updates.md`](references/phase-3-documentation-updates.md).
148
+ > Always runs. Refreshes the session-lock heartbeat at entry (`updateHeartbeat`, #590-3 — skip when `persistence: false`) so a long close-out cannot lapse the 4h TTL, then walks 3.0 Defensive Cleanup → 3.1 SSOT files → 3.2 Docs Verification → 3.2a Session Handover → 3.3 Claude-rules freshness → 3.4/3.4a STATE.md write + coordinator-snapshot cleanup → 3.45 Telemetry Flush → 3.5/3.5a/3.6.x session memory, learning extraction and the mechanical skip-plan tail → 3.7/3.7a/3.7b/3.7c/3.7d/3.7e metrics write, recommendations, durable commit (#490), vault board → closed, session-eval, vault orphans named (#1563). Full procedure: [`references/phase-3-documentation-updates.md`](references/phase-3-documentation-updates.md).
149
149
 
150
150
  ## Phase 3.8: Session Lock Release (#330)
151
151
 
@@ -305,7 +305,7 @@ Present to the user the **Session Summary**: Completed / Carried Over / Dropped
305
305
  | `metrics-collection.md` | Phase 1.7 JSONL schema and conditional field rules |
306
306
  | `vault-operations.md` | Phase 2.1 validator bash contract and reporting matrix |
307
307
  | `drift-operations.md` | Phase 2.2 drift-checker bash contract and reporting matrix |
308
- | `references/phase-3-documentation-updates.md` | Phase 3 full procedural body — final heartbeat (#590-3), 3.0 Defensive Cleanup, 3.1 SSOT files, 3.2/3.2a docs + handover, 3.3 rules freshness, 3.4/3.4a STATE.md write + snapshot cleanup, 3.45 Telemetry Flush, 3.5/3.5a/3.6.x memory + learnings + tail dispatcher, 3.7/3.7a/3.7b/3.7c/3.7d metrics, recommendations, durable commit, vault board, session-eval |
308
+ | `references/phase-3-documentation-updates.md` | Phase 3 full procedural body — final heartbeat (#590-3), 3.0 Defensive Cleanup, 3.1 SSOT files, 3.2/3.2a docs + handover, 3.3 rules freshness, 3.4/3.4a STATE.md write + snapshot cleanup, 3.45 Telemetry Flush, 3.5/3.5a/3.6.x memory + learnings + tail dispatcher, 3.7/3.7a/3.7b/3.7c/3.7d/3.7e metrics, recommendations, durable commit, vault board, session-eval, vault orphans |
309
309
  | `phase-3-2-docs-verification.md` | Phase 3.2 full procedural body — docs-tasks load, SESSION_START_REF, per-task loop, mode-gated report, Documentation Coverage block |
310
310
  | `learning-patterns.md` | Phases 3.5a + 3.6 extraction heuristics, confidence updates, passive decay, and JSONL write procedure |
311
311
  | `phase-3-6-tail.md` | Phase 3.6.x tail — detail procedures for the tail phases: 3.6.3 Memory-Proposals Collection (`collectProposals` + AUQ multiSelect + `promoteAndClear`, composing `writeApproved` + `clearProposalsJsonl` behind a mechanical write-before-clear guard, #828), **3.6.4 Expired-Learnings Sweep — MECHANICAL since 2026-09-09**: after `planTailPhases()`, call `runTailPhases({ repoRoot, plan })` from `scripts/lib/session-end/tail-runner.mjs` (delegating to `runExpiredSweep`) and report `result['3.6.4']` (`ran`, `scanned`, `archived`); the event `orchestrator.learnings.sweep_applied` is the proof it ran (Epic #723 B4), **3.6.5 Auto-Dream — RETIRED** and **3.6.7 Auto-Dialectic — RETIRED** (both replaced by the session-start `maintenance-due` probe, `checkMaintenanceDue` in `scripts/lib/maintenance-due-banner.mjs`; headings kept as two-line stubs because other docs cite them), 3.6.6 Skill-Applied Judge (#645 L3 — two calls, not one: `buildSkillEvidence` from `scripts/lib/skill-evidence-window.mjs` renders this session's transcript into the evidence window, then `runSkillJudge` judges it and the coordinator writes each judgment via `appendSkillJudgment`; on empty evidence text `runSkillJudge` returns `status: 'no-evidence'` and does NOT dispatch, #1399 — the exact call shape is in the sub-file, do not reconstruct it here), 3.6.8 Reconciliation Rule Proposals (#696 FA3 — `runReconcile` + AUQ + `writeApprovedRules`). Loaded on demand by the SKILL.md skip-plan dispatcher (#724) — only phases with `run: true` in the `planTailPhases()` plan execute |
@@ -316,6 +316,7 @@ Present to the user the **Session Summary**: Completed / Carried Over / Dropped
316
316
  | `phase-3-7a-recommendations.md` § 3.7b | Phase 3.7b full procedural body — `withDurableCommit` invocation for `sessions.jsonl` + `STATE.md` (#490 AC2), `enabled:false` local no-op, autopilot.jsonl exclusion note |
317
317
  | `references/phase-3-documentation-updates.md` § 3.7c | Vault Board → Closed (#674) — `mirrorBoard({ explicitStatus: 'closed' })` transitions this repo's board row to `closed`; gated on `vault-integration.enabled`, generator-marked + idempotent, non-blocking, ordered after 3.7b and before 3.7d/3.4/3.8 |
318
318
  | `references/phase-3-documentation-updates.md` § 3.7d | Session-Eval (opt-in — #803) — `node scripts/eval-session.mjs --json` scores the just-closed session; gated on `eval.enabled` + `eval.mode != off` (parsed by `scripts/lib/config/eval.mjs`), optional `eval-judge` dispatch + `writeEvalReport`, advisory/never-blocks-close, ordered after 3.7 (record must exist) and before 3.4/Phase 4 (record committed with the session). Full flow in `skills/eval/SKILL.md` |
319
+ | `references/phase-3-7e-vault-orphans.md` | Phase 3.7e Vault Orphans (#1563) — `node scripts/vault-orphans.mjs --since <started_at> --json` (`findVaultOrphans` in `scripts/lib/session-end/vault-orphans.mjs`, read-only `git ls-files --others`) names untracked vault files modified since the session start, minus `_generator: session-orchestrator-` files; candidates only (mtime is no proof), one Open Question via `appendOpenQuestionOnDisk`, never commits/moves/deletes in the vault; `unavailable` = "could not measure", never "no orphans"; gated on `vault-integration.enabled`, ordered after 3.7d and before 3.4 |
319
320
  | (inline) Phase 3.8 | Session Lock Release — `release()` uses the physical raw `session_id`; raw mismatch/absent is non-fatal but never repaired with semantic labels or proof (live ambiguity remains for TTL/Reaper); fs-errors are non-fatal; runs after STATE.md writes and before Phase 4 commit staging |
320
321
  | (inline) Phase 4 | Commit & Push — stage individually (PSA-004), commit, push to origin, then the `github-mirror-push` block (4 states: not-a-repo / no `github` remote / pushed / push failed) |
321
322
  | `references/phase-4a-worktree-cleanup.md` | Phase 4a full procedural body — auto-promoted-worktree detection (`detectAutoPromotedWorktree`, marker-keyed since #1069), clean-check, clean auto-remove path, dirty 3-option AUQ (`Behalten`/`Löschen`/`Manuell`), PSA-003 + #490 ordering rationale |
@@ -0,0 +1,63 @@
1
+ # Phase 3.7e: Vault Orphans (#1563)
2
+
3
+ > Sub-file of the session-end skill (#1157 - agentskills.io: SKILL.md core < 500 lines, procedure in `references/`). `SKILL.md` and `references/phase-3-documentation-updates.md` keep a short stub naming this phase and its gate condition.
4
+
5
+ ## Why
6
+
7
+ A session that writes into the Meta-Vault (an audit, a report, a review, a handover) leaves an untracked file in ANOTHER repo. Its own close commits only in its own repo, and vault-mirror auto-commits only its own generator-marked files in `40-learnings/` and `50-sessions/` (`scripts/lib/vault-mirror/auto-commit.mjs`). Nothing else ever looks. Measured 2026-10-11: 268 untracked files had piled up in one vault checkout over five days. The writing session is the only one that knows it wrote them, so this phase makes it look before it closes.
8
+
9
+ ## Gate
10
+
11
+ - Skip silently unless `vault-integration.enabled: true` in Session Config.
12
+ - Skip silently when `<state-dir>/STATE.md` does not exist or has no `started_at` in its frontmatter (`persistence: false`): there is no session window to measure against and no place to record the result.
13
+
14
+ ## Ordering
15
+
16
+ Runs AFTER Phase 3.7d (Session-Eval) and BEFORE Phase 3.4 (`status: completed`), so the Open Question below is written while STATE.md is still `status: active`. See the Phase 3.4 Runtime Ordering Note.
17
+
18
+ ## Procedure
19
+
20
+ 1. Read `started_at` from the STATE.md frontmatter (the same value Phase 3.7 writes into `sessions.jsonl`).
21
+ 2. Run the read-only probe from the repo root, so the host-local vault-dir resolution (`SO_VAULT_DIR` > owner.yaml > committed `vault-integration.vault-dir`) sees this repo's Session Config:
22
+
23
+ ```bash
24
+ node "$PLUGIN_ROOT/scripts/vault-orphans.mjs" --since "<STATE.md started_at>" --json
25
+ ```
26
+
27
+ Exit `0` = measured (the JSON may hold zero candidates), `1` = bad arguments (fix the call), `2` = could not measure. The JSON is the result of `findVaultOrphans()` in `scripts/lib/session-end/vault-orphans.mjs`:
28
+
29
+ - `{ status: 'ok', candidates: [{ path, mtimeMs }], total, truncated, untracked }` - `path` is vault-relative; `candidates` holds at most 200 entries sorted by path, `total` counts all of them, `untracked` is everything git listed before the filters.
30
+ - `{ status: 'unavailable', reason, detail?, candidates: [] }` - no vault dir, not a git repo, or git failed.
31
+
32
+ A candidate is an untracked, not gitignored vault file whose mtime is at or after `started_at` and whose first 4 KB carry no `_generator: session-orchestrator-` frontmatter line (those files belong to vault-mirror, the narrative mirror, the active-sessions board or the portfolio writer).
33
+
34
+ 3. Disposition:
35
+
36
+ - **`total > 0`** - NAME the candidates in the Final Report (see `session-summary-template.md`, line `Vault orphans`), then record ONE Open Question in STATE.md, listing up to 10 paths and the count:
37
+
38
+ ```javascript
39
+ import { appendOpenQuestionOnDisk } from '${PLUGIN_ROOT}/scripts/lib/state-md.mjs';
40
+
41
+ const shown = result.candidates.slice(0, 10).map((c) => c.path);
42
+ const more = result.total - shown.length;
43
+ await appendOpenQuestionOnDisk(process.cwd(), {
44
+ question:
45
+ `Vault: ${result.total} untracked file(s) modified during this session: ` +
46
+ `${shown.join(', ')}${more > 0 ? ` (+${more} more)` : ''}. ` +
47
+ 'Commit, move or delete them in the vault - mtime is a hint, not proof this session wrote them.',
48
+ source: 'session-end/3.7e',
49
+ priority: 'medium',
50
+ });
51
+ ```
52
+
53
+ The question survives the next session-start Idle Reset and is surfaced there as a forced read (`skills/_shared/state-ownership.md` Open Questions), so the next session or the vault owner sorts the files in.
54
+ - **`total === 0`** - report `none since session start` in the Final Report. No Open Question.
55
+ - **`status: unavailable`** (exit 2) - report `could not measure (<reason>)`. NEVER report it as "no orphans": a missing measurement is not a zero. No Open Question.
56
+
57
+ ## What this phase never does
58
+
59
+ It does NOT commit into the vault, does NOT delete, does NOT move anything (PSA-003). The mtime window does not prove that this session wrote a file - a concurrent session of another repo may have written the same file in the same window - and the vault is another repo with its own rules. The phase reports; the vault owner disposes.
60
+
61
+ **Non-blocking:** a probe failure, a non-zero exit or a failed STATE.md write MUST NOT block the close. Log one `WARNING: vault orphans - <reason>; continuing close` line and proceed.
62
+
63
+ No Session Config key and no event type belong to this phase; it is a report.
@@ -65,7 +65,7 @@ Review `<state-dir>/rules/` files that are relevant to this session's work:
65
65
 
66
66
  > **Ownership Reference:** See `skills/_shared/state-ownership.md`. session-end is authorized to set `status: completed` plus the optional `updated` timestamp (#184), and — as of Phase A of Epic #271 — the 5 Recommendation fields written by Phase 3.7a. No other fields.
67
67
 
68
- > **Runtime Ordering Note (Epic #271 Phase A):** Phase 3.4's `status: completed` write executes LAST in Phase 3, AFTER Phase 3.7 (sessions.jsonl) and Phase 3.7a (Compute and Write Recommendations). The ordinal position here (3.4) is kept for historical compatibility; the canonical runtime order is `3.1 → 3.2 → 3.3 → 3.4a → 3.5 → 3.5a → 3.6 → 3.6.3 → 3.6.4 → 3.6.6 → 3.6.8 → 3.7 → 3.45 → 3.7a → 3.7b → 3.7c → 3.7d → 3.4` (3.6.3/3.6.4/3.6.6 were missing from this note pre-#724; 3.6.5 Auto-Dream and 3.6.7 Auto-Dialectic were RETIRED 2026-09-09 — see `phase-3-6-tail.md` — leaving four live tail phases, not six; the Tail-Diät skip-plan dispatcher dispatches exactly those four mechanically). Rationale: Phase 3.7a reads in-memory session metrics and writes the 5 Recommendation fields via `updateFrontmatterFields`; that write must complete BEFORE the STATE.md frontmatter is finalized with `status: completed` so the Recommendation fields are visible to the next session-start while STATE.md is still `status: active`. Crash-resilience: if `/close` aborts between 3.7a and 3.4, STATE.md carries `status: active` + Recommendations; session-start Phase 1.5 offers resume (and the banner renders). If the reverse ordering were used (status: completed first), a crash would leave `status: completed` without Recommendations — the Reader would silently no-op the banner, losing the handoff. Phase 3.45 (Telemetry Flush, #844) sits AFTER Phase 3.7 because it drains the send-queue with the just-written `sessions.jsonl` record already included, and BEFORE Phase 3.7a because it is a fire-and-forget side-effect with no dependency on the Recommendation-write ordering below it. Phase 3.7d (Session-Eval, #803) sits AFTER Phase 3.7 because it scores the `sessions.jsonl` record that phase just wrote — the record must exist first — and BEFORE Phase 3.4 because its `eval.jsonl` output is advisory and must never block the close.
68
+ > **Runtime Ordering Note (Epic #271 Phase A):** Phase 3.4's `status: completed` write executes LAST in Phase 3, AFTER Phase 3.7 (sessions.jsonl) and Phase 3.7a (Compute and Write Recommendations). The ordinal position here (3.4) is kept for historical compatibility; the canonical runtime order is `3.1 → 3.2 → 3.3 → 3.4a → 3.5 → 3.5a → 3.6 → 3.6.3 → 3.6.4 → 3.6.6 → 3.6.8 → 3.7 → 3.45 → 3.7a → 3.7b → 3.7c → 3.7d → 3.7e → 3.4` (3.6.3/3.6.4/3.6.6 were missing from this note pre-#724; 3.6.5 Auto-Dream and 3.6.7 Auto-Dialectic were RETIRED 2026-09-09 — see `phase-3-6-tail.md` — leaving four live tail phases, not six; the Tail-Diät skip-plan dispatcher dispatches exactly those four mechanically). Rationale: Phase 3.7a reads in-memory session metrics and writes the 5 Recommendation fields via `updateFrontmatterFields`; that write must complete BEFORE the STATE.md frontmatter is finalized with `status: completed` so the Recommendation fields are visible to the next session-start while STATE.md is still `status: active`. Crash-resilience: if `/close` aborts between 3.7a and 3.4, STATE.md carries `status: active` + Recommendations; session-start Phase 1.5 offers resume (and the banner renders). If the reverse ordering were used (status: completed first), a crash would leave `status: completed` without Recommendations — the Reader would silently no-op the banner, losing the handoff. Phase 3.45 (Telemetry Flush, #844) sits AFTER Phase 3.7 because it drains the send-queue with the just-written `sessions.jsonl` record already included, and BEFORE Phase 3.7a because it is a fire-and-forget side-effect with no dependency on the Recommendation-write ordering below it. Phase 3.7d (Session-Eval, #803) sits AFTER Phase 3.7 because it scores the `sessions.jsonl` record that phase just wrote — the record must exist first — and BEFORE Phase 3.4 because its `eval.jsonl` output is advisory and must never block the close.
69
69
 
70
70
  > Gate: Only run if `persistence` is enabled in Session Config and `<state-dir>/STATE.md` exists.
71
71
  1. Set frontmatter `status: completed`
@@ -239,3 +239,13 @@ Evaluate the just-closed session deterministically and, when configured, with an
239
239
 
240
240
  **Advisory — never blocks the close (FA6):** an eval failure — a non-zero `eval-session.mjs` exit, a judge-dispatch error, or a report-write error — MUST NOT abort `/close`. Under `mode: warn`, log a single `WARNING: session-eval failed — <reason>; continuing close` line to stderr and proceed to Phase 3.8 / Phase 4. There is NO exit-code gate on this phase. See `skills/eval/SKILL.md` for the full deterministic-engine + judge + report detail flow.
241
241
 
242
+ ### Phase 3.7e: Vault Orphans (#1563)
243
+
244
+ > Gate: Skip silently unless `vault-integration.enabled: true` in Session Config, and when STATE.md has no `started_at` (no session window to measure).
245
+
246
+ > **Ordering:** Runs AFTER Phase 3.7d and BEFORE Phase 3.4 (`status: completed`), so its one Open Question lands while STATE.md is still `status: active`. See the Phase 3.4 Runtime Ordering Note canonical order.
247
+
248
+ Names the untracked vault files this session may have left behind: `node "$PLUGIN_ROOT/scripts/vault-orphans.mjs" --since <STATE.md started_at> --json` lists untracked vault files modified since the session start, minus files carrying a `_generator: session-orchestrator-` marker. The results are candidates — mtime is a hint, not proof of authorship. The coordinator names them in the Final Report and records ONE Open Question via `appendOpenQuestionOnDisk` (up to 10 paths plus the count). It never commits, moves or deletes anything in the vault (PSA-003). Exit 2 / `status: unavailable` is reported as "could not measure", never as "no orphans". Non-blocking.
249
+
250
+ **See `phase-3-7e-vault-orphans.md` for full details.**
251
+
@@ -46,6 +46,10 @@ Present to the user:
46
46
  - Custom Phases: [render based on Phase 2.5 result — omit the line entirely if `custom-phases` was absent/empty]
47
47
  - Per phase: `<name>: <pass|FAIL> (exit <code>, mode=<mode>)[ — review: <path>]`
48
48
  - None ran (all filtered out by `when`): `none applicable for session-type=<type>.`
49
+ - Vault orphans: [render based on Phase 3.7e — omit the line entirely when `vault-integration.enabled` is not `true`]
50
+ - Candidates present: `<N> untracked vault file(s) modified since session start (candidates, mtime is no proof): <path>, <path>, ... — recorded as Open Question, nothing committed or deleted.`
51
+ - None: `none since session start (<U> untracked in total).`
52
+ - Could not measure (exit 2 / `status: unavailable`): `could not measure (<reason>)` — never "none".
49
53
  - Enforcement: [N violations blocked / M warnings] (or "N/A" if enforcement off)
50
54
  - Circuit breaker: [N agents hit limits, M spirals detected] (or "none")
51
55
  - Metrics written to: `.orchestrator/metrics/sessions.jsonl`
@@ -352,7 +352,7 @@ Invokes `buildLiveSignals` (single SSOT for the signals shape) then `selectMode(
352
352
 
353
353
  ## Phase 7.6: Fleet Check-in (#1462)
354
354
 
355
- > Skip silently when `persistence: false` (no ledger for the event). Runs BEFORE the first writing action; everything not stated here is in `skills/_shared/fleet-protocol.md`.
355
+ > Skip silently when `persistence: false` (no ledger for the event). Runs BEFORE the first writing action; everything not stated here is in `skills/_shared/fleet-protocol.md`. Without fleet integration the CLI itself skips (stdout `skipped: "no-fleet"`, no file, no event, #1559): then this phase ends there — no hint, no `auflagen/` read, and no Standard-Auflagen, except for a headless run (`plattform: kopflos`), which applies them at once.
356
356
 
357
357
  Build the check-in JSON (fields per the reference; `session` from `.orchestrator/current-session.json`, `modus` = session type, `kandidaten` = the issue numbers you intend to claim) and pipe it into `node "${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-$PLUGIN_ROOT}}/scripts/fleet-checkin.mjs"` — it validates, stores `checkin/<session_id>.json` (0600) under `~/.config/navigator/` and emits `orchestrator.fleet.checkin`. Its stdout carries `navigator_state` and `navigator_adresse` (the lease's validated `adresse`, else `null`): on `active`, and only when `navigator_adresse` is non-null and reachable via `ListAgents`, send ONE hint to exactly that name, naming the file path — never expect or wait for a reply (CSM-004). Then read `auflagen/<session_id>.json` via `node "${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-$PLUGIN_ROOT}}/scripts/fleet-auflagen.mjs" <session_id>` (only a file whose `repo` resolves to this repo's git common dir is `accepted`; a `rejected` one counts as absent); if it is still absent at the stdout's `fallback_due_at`, the reference's Standard-Auflagen apply (the CLI computes that deadline: `zeit` plus `CHECKIN_FALLBACK_MIN` while a navigator is active, `zeit` itself — immediately — otherwise). Reading work and edits in the own worktree continue meanwhile.
358
358
 
@@ -7,7 +7,7 @@ Run immediately before Phase 8 so the Mode-Selector recommendation can influence
7
7
 
8
8
  ## Distinction from Phase 1.5 Recommendations Banner
9
9
 
10
- Phase 1.5 renders a `📋` banner that reads the **previous** session's archived Recommendation fields from STATE.md (`recommended-mode`, `rationale`, `completion-rate`, etc., written by session-end Phase 3.7a). It is a backward-looking handoff signal.
10
+ Phase 1.5 renders a `📋` banner that reads the **previous** session's Recommendation fields from the STATE.md frontmatter (`recommended-mode`, `rationale`, `completion-rate`, etc., written by session-end Phase 3.7a). It is a backward-looking handoff signal.
11
11
 
12
12
  Phase 7.5 runs `selectMode(signals)` — a **forward-looking** computation over live signals gathered this session (current carryover ratios, recent sessions trend, learnings, bootstrap tier). It emits a `📊` banner.
13
13
 
@@ -45,6 +45,8 @@ truncated window (fixed in `c20d4d2`).
45
45
 
46
46
  **Key source bindings (Phase → field):**
47
47
 
48
+ The five Recommendation fields are read from the STATE.md frontmatter that session-end Phase 3.7a wrote at the previous `/close`. The Phase 1.5 Idle Reset keeps them there (#1560; before, it deleted them and this step saw `recommendedMode: null`, confidence 0); the "Phase" column names the phase that surfaces them first, not a writer.
49
+
48
50
  | `signals` field | Populated from | Phase |
49
51
  |---|---|---|
50
52
  | `recommendedMode` | `parseRecommendations(frontmatter).mode` | Phase 1.5 |
@@ -98,14 +98,22 @@ When (and only when) the prior `status` is `completed`, rewrite STATE.md to a cl
98
98
 
99
99
  Reset rules — applies ONLY on the `completed` branch. Do NOT perform this reset on `active` or `paused`; those paths stay user-interactive via AskUserQuestion.
100
100
 
101
+ Run it as code, after the Recommendations Banner — never rewrite STATE.md by hand (#1560):
102
+
103
+ ```bash
104
+ node "${PLUGIN_ROOT}/scripts/state-md-idle-reset.mjs" --json
105
+ ```
106
+
107
+ It prints `{"changed": <bool>, "reason": <string|null>, "path": "<STATE.md>"}` and writes under the STATE.md lock (`resetStateMdToIdle` in `scripts/lib/state-md/idle-reset.mjs`). A no-op exits 0 with `changed: false` and one of `reason: "status-not-completed"` (any status other than `completed`), `"unparseable"` (no frontmatter) or `"missing"` (no or empty STATE.md). Exit 2 means `--repo-root` is not a directory, the write failed, or a STATE.md guard refused it (`reason` names the guard) — report it as a Deviation and continue. Without a new `## Wave History` (a coordinator-direct session) the earlier `## Previous Session` body is kept below the new recommendations copy. The rules below are the contract that code implements:
108
+
101
109
  1. Set frontmatter `status: idle`.
102
110
  2. Clear `current-wave` (set to `0`).
103
- 3. Move the existing `## Wave History` body into a new `## Previous Session` archive section (retain the record, but demote it below the new session's live state). Remove the original `## Wave History` section — wave-executor will recreate it on the next wave.
111
+ 3. Move the existing `## Wave History` body into a new `## Previous Session` archive section under `### Wave History (<session>)`, replacing any earlier `## Previous Session` section (retain the record, but demote it below the new session's live state). Remove the original `## Wave History` section — wave-executor will recreate it on the next wave.
104
112
  4. Clear `## Deviations` (leave the heading with an empty body so the schema is preserved).
105
113
  - **PRESERVE `## What Not To Retry` (#623):** do NOT clear, demote, or drop this section during the Idle Reset. Unlike `## Deviations` (per-session, emptied above) and `## Wave History` (demoted into `## Previous Session`), `## What Not To Retry` is a **cross-session continuity slot** — its entries must survive into the next session so session-start Phase 6.5.1 can surface them. Leave the section, its heading, and all entries byte-for-byte intact.
106
114
  - **PRESERVE `## Open Questions` (#772):** do NOT clear, demote, or drop this section during the Idle Reset. Unlike `## Deviations` (per-session, emptied above) and `## Wave History` (demoted into `## Previous Session`), `## Open Questions` is a **cross-session continuity slot** — unanswered entries must survive into the next session so session-start Phase 6.5.2 can surface them as a forced-read. Leave the section, its heading, and all entries (answered and unanswered) byte-for-byte intact.
107
115
  5. Leave other frontmatter fields (`schema-version`, `session-type`, `branch`, `issues`, `started_at`, `total-waves`) intact until Phase 1b overwrites them with the new session's values.
108
- 6. **v1.1 Recommendation-field archival (Epic #271 Phase A, AC2):** If ANY of the 5 Recommendation fields (`recommended-mode`, `top-priorities`, `carryover-ratio`, `completion-rate`, `rationale`) is present in the frontmatter, remove them from the frontmatter via `updateFrontmatterFields(contents, {field: null, ...})` (null value deletes the key). Then prepend a readable block (NOT YAML) to the `## Previous Session` body:
116
+ 6. **v1.1 Recommendation fields STAY in the frontmatter (Epic #271 Phase A, AC2; changed by #1560):** do NOT remove `recommended-mode`, `top-priorities`, `carryover-ratio`, `completion-rate`, `rationale`. They are the handoff Phase 7.5 reads; session-end Phase 3.7a, their only writer, overwrites them at the next `/close`. If ANY of them is present, also prepend a readable copy (NOT YAML) to the `## Previous Session` body:
109
117
 
110
118
  ```markdown
111
119
  ### Recommendations (archived from v1.1 frontmatter)
@@ -117,9 +125,9 @@ Reset rules — applies ONLY on the `completed` branch. Do NOT perform this rese
117
125
  ```
118
126
 
119
127
  Omit individual bullets for null-valued fields. If all 5 are null (i.e., `parseRecommendations` returned non-null but every field is null after type-coercion), skip the archival block entirely.
120
- 7. **Scope-baseline key deletion (Epic #894 S5, #898):** If ANY of the 5 `scope-baseline-*` frontmatter keys (`scope-baseline-intent`, `scope-baseline-owner-boundary`, `scope-baseline-planned-files`, `scope-baseline-session`, `scope-baseline-frozen-at`) is present, remove them via the same `updateFrontmatterFields(contents, {field: null, ...})` mechanism as rule 6 (null value deletes the key). Rule 5 leaves unknown frontmatter fields intact and no other rule removes these five — without this step they survive into session N+1 and silently corrupt the next session's drift-baseline denominator. This is a hygiene layer only: the primary defense is mechanical — `scripts/lib/scope-baseline.mjs` compares `scope-baseline-session` against the canonical `session` field, so a stale baseline self-invalidates (`readBaseline()` returns `{stale: true, …}`) even if this rule were skipped. Delete exactly these five keys; do not remove any other unknown key.
128
+ 7. **Scope-baseline key deletion (Epic #894 S5, #898):** If ANY of the 5 `scope-baseline-*` frontmatter keys (`scope-baseline-intent`, `scope-baseline-owner-boundary`, `scope-baseline-planned-files`, `scope-baseline-session`, `scope-baseline-frozen-at`) is present, remove them via `updateFrontmatterFields(contents, {field: null, ...})` (null value deletes the key). Rule 5 leaves unknown frontmatter fields intact and no other rule removes these five — without this step they survive into session N+1 and silently corrupt the next session's drift-baseline denominator. This is a hygiene layer only: the primary defense is mechanical — `scripts/lib/scope-baseline.mjs` compares `scope-baseline-session` against the canonical `session` field, so a stale baseline self-invalidates (`readBaseline()` returns `{stale: true, …}`) even if this rule were skipped. Delete exactly these five keys; do not remove any other unknown key.
121
129
 
122
- Rationale: `/close` intentionally keeps STATE.md as a record so the next session-start can read it. This reset completes that contract by demoting the record before new session state is written, so a fresh session never appears "already completed". The Recommendation archival (rule 6) preserves the session-to-session handoff in a human-readable form after the Recommendations Banner has rendered — Phase B's Mode-Selector will read the LIVE frontmatter of the current session and does not need the archived copy, so this is purely informational for humans browsing STATE.md history.
130
+ Rationale: `/close` intentionally keeps STATE.md as a record so the next session-start can read it. This reset completes that contract by demoting the record before new session state is written, so a fresh session never appears "already completed". Rule 6 keeps the Recommendation fields because the Phase 7.5 Mode-Selector (`buildLiveSignals()`) reads them from this same frontmatter later in session-start, and the current session writes its own only at session-end Phase 3.7a. Deleting them (the rule until #1560) left the selector with no recommendation after every clean `/close`: `{"mode":"feature","rationale":"missing/invalid recommendedMode → default","confidence":0}`. The archived block is a human-readable copy for browsing STATE.md history.
123
131
 
124
132
  ### Snapshot Recovery (#196)
125
133
 
package/AGENTS.md DELETED
@@ -1,207 +0,0 @@
1
- # Session Orchestrator Plugin
2
-
3
- > Project-instruction file resolution: this is `CLAUDE.md` on Claude Code / Cursor IDE; the equivalent file on Codex CLI is `AGENTS.md`. See [skills/_shared/instruction-file-resolution.md](skills/_shared/instruction-file-resolution.md).
4
-
5
- > Lean root by design (Anthropic large-codebase best-practice: root = pointers + critical gotchas). Delegated docs:
6
- > - **Install, CLI usage, architecture, component inventory** → [`README.md`](./README.md) (full inventory: [`docs/components.md`](./docs/components.md))
7
- > - **Plugin ↔ private baseline relationship** (what degrades without it, the public fallback) → [`docs/baseline.md`](./docs/baseline.md)
8
- > - **Sub-agent authoring spec** (frontmatter, body, `sandbox-tier`, `output-schema`) → [`docs/agent-authoring.md`](./docs/agent-authoring.md) (moved out of `agents/` in 4.0.0 — the plugin loader registers every `agents/*.md` by directory convention, and the spec was dispatched as an agent 5× fleet-wide)
9
- > - **Stable product/tech/structure context** → [`.orchestrator/steering/`](./.orchestrator/steering/) (injected at session-start Phase 2.6)
10
- > - **Always-on + path-scoped rules** → [`.claude/rules/`](./.claude/rules/) (per-wave via `rule-loader.mjs`, #336/#694); authoring spec → [`docs/rule-authoring.md`](./docs/rule-authoring.md)
11
- > - **Decisions log** (hand-authored) → [[01-projects/session-orchestrator/decisions]] in the Meta-Vault
12
- > - **Session narrative** (machine-written by session-end Phase 3.7 via `scripts/lib/vault-status/narrative-mirror.mjs`) → `01-projects/session-orchestrator/_session-narrative.md`
13
- > - **Operator tmux side-channel** → `/tmux-layout` (4-pane: STATE.md/CI-watch/events; [ADR-0007](docs/adr/0007-tmux-visualization-substrate.md))
14
- >
15
- > **Root `AGENTS.md` is GENERATED byte-identical from this file** (`node scripts/generate-agents-skills.mjs`) for harnesses that read only `AGENTS.md` (Codex CLI, OpenCode, Kiro, Cursor's AGENTS path). Never edit it; edit here and regenerate. `validate-plugin` fails on drift.
16
-
17
- ## Current State <!-- consistency:exempt:lean-root-pointer-section -->
18
-
19
- State-free by design (see the **Live state is not in this file** gotcha below) — SSOTs:
20
- - **Version + test/coverage** → README badges
21
- - **Per-session metrics & history** → [`.orchestrator/metrics/sessions.jsonl`](./.orchestrator/metrics/sessions.jsonl)
22
- - **Decisions** (hand-authored) → [[01-projects/session-orchestrator/decisions]] (Meta-Vault) · **Session narrative** (generated) → `_session-narrative.md` beside it
23
-
24
- ## Critical Gotchas <!-- consistency:exempt:lean-root-pointer-section -->
25
-
26
- These are the non-obvious, mistake-causing facts that must load every session. Everything else is delegated above.
27
-
28
- - **CI status is the source of truth at session-start** — never claim CI green from `npm test` alone (8-pipeline silent regression 2026-05-09 → 2026-05-10, fixed in deep-2); Phase 4 🚨 banner `checkCiStatus({ repoRoot })` in `scripts/lib/ci-status-banner.mjs`; see `skills/session-start/references/phase-4-ssot-environment-check.md` (incident: ADR-0006). <!-- consistency:exempt:runtime-only -->
29
- - **Destructive-Command Guard** (`hooks/pre-bash-destructive-guard.mjs`, `.orchestrator/policy/blocked-commands.json`: 12 block / 4 warn of 16 rules) is live on Claude Code + Cursor/Pi bridges, instruction-only on Codex. PSA-003 (`parallel-sessions.md`); bypass `allow-destructive-ops: true`; long form incl. #1401: `docs/session-config-reference.md`. <!-- consistency:exempt:runtime-only -->
30
- - **Session Config below is runtime-critical.** `scripts/parse-config.mjs` parses the `## Session Config` block; `claude-md-drift-check` Check 6 enforces top-level-key parity against `docs/session-config-template.md`. Edit it like code, not prose — a dropped key changes runtime behaviour.
31
- - **Live state is not in this file.** Stack: Node 24+, vitest, ESLint 10 (`npm ci` after clone). Test counts, backlog, version, component inventory drift fast — the SSOT is README badges + `.orchestrator/metrics/sessions.jsonl`. Per-session detail lives in the Meta-Vault decisions log (linked above), not here.
32
- - **`memory.propose` requires `SO_WAVE_AGENT=1`** — `scripts/memory-propose.mjs` exits 3 from the coordinator thread (use `/evolve`); wave-executor sets it per dispatched agent. Statuses: queued 0 · dry-run-ok 0 · quota-exceeded 1 · rejected-low-confidence 2 · rejected-wrong-context 3 · error 4 — `docs/session-config-reference.md` § Memory Proposals. <!-- consistency:exempt:runtime-only -->
33
- - **Auto-promoted worktree cleanup keys on the `.orchestrator/promoted-from.json` marker, not on session-id coincidence (#1069)** — promotion is a process boundary (ADR-0013), so `detectAutoPromotedWorktree()` tries the marker first (`source: 'marker'`) and falls back to the `<repo>-<sessionId>` basename only for pre-marker worktrees.
34
- `/close` Phase 4a runs AFTER Phase 4 commit+push (#490): clean → auto-remove with WARN, dirty → AUQ `[Behalten/Löschen/Manuell]`; Hybrid Pattern (Anthropic-style, ADR-0008), PSA-003. Long form: `skills/session-end/references/phase-4a-worktree-cleanup.md`. <!-- consistency:exempt:runtime-only -->
35
- - **`allowedPaths` is COMPUTED, and the scope declaration has TWO shapes — writing only one is the silent failure (#1020).** (a) per-agent `<state-dir>/filescopes/wave-<N>/<agent-id>.json` (path strings = `$AGENT_FILESCOPE_JSON`: FILE-SCOPE injection, Learnings-Index, `--assert-subset`); (b) per-wave `{id, files}` records, the only input of `--assert-disjoint`/`--union`.
36
- `node scripts/materialize-wave-scope.mjs --state-dir <state-dir> --wave <N>` writes both; fold `coordinator.json` into (b). Skipping (a) = signal-free ALLOW (2026-08-19: six waves, ~27 dispatches, zero injection). Long form: `docs/scope-collision-guard.md` § The two-shape trap; `skills/wave-executor/references/wave-loop-scope-manifest.md` § 3.1/3.2. <!-- consistency:exempt:runtime-only -->
37
- - **`vault-dir` resolves HOST-LOCALLY** (`SO_VAULT_DIR` > `owner.yaml` > committed `vault-integration.vault-dir`, `scripts/lib/config/host-paths.mjs`) — a hand-run vault writer with a synthetic `repoRoot` still writes into the REAL vault; export `SO_VAULT_DIR=<tmpdir>` before any manual invocation. Detail: `docs/session-config-reference.md` (#1448). <!-- consistency:exempt:runtime-only -->
38
-
39
- ## Session Config
40
-
41
- persistence: true
42
- enforcement: warn
43
- agents-per-wave: 6 (deep: 18)
44
- waves: 5
45
- recent-commits: 20
46
- test-command: npm test
47
- typecheck-command: npm run typecheck
48
- lint-command: npm run lint
49
- stale-branch-days: 7
50
- plugin-freshness-days: 30
51
- plan-baseline-path: OVERRIDE-IN-owner.yaml # placeholder, NOT a real path — resolve host-locally
52
- plan-prd-location: docs/prd
53
- plan-retro-location: docs/retro
54
- plan-default-visibility: internal
55
- vcs: gitlab
56
- auto-skill-dispatch: false
57
- vault-integration:
58
- enabled: true
59
- vault-dir: ~/Projects/vault
60
- mode: warn
61
- vault-name:
62
- docs-orchestrator:
63
- enabled: false
64
- audiences: [user, dev, vault]
65
- mode: warn
66
- vault-staleness:
67
- enabled: false
68
- thresholds:
69
- top: 30
70
- active: 60
71
- archived: 180
72
- mode: warn
73
- docs-staleness:
74
- enabled: false
75
- thresholds:
76
- living: 90
77
- mode: warn
78
- moc-staleness:
79
- enabled: false
80
- thresholds:
81
- moc: 90
82
- mode: warn
83
- context-coverage:
84
- enabled: false
85
- mode: warn
86
- worktree-orphans:
87
- enabled: false
88
- base-branch: main
89
- mode: warn
90
- drift-check:
91
- enabled: true
92
- mode: warn
93
- check-docs-parity: true
94
- wave-reviewers:
95
- enabled: false
96
- reviewers: []
97
- mode: warn
98
- memory-cleanup-soft-limit: 180
99
- vault-mirror:
100
- quality:
101
- min-narrative-chars: 400
102
- min-confidence: 0.5
103
- memory:
104
- banner:
105
- enabled: true
106
- proposals:
107
- enabled: true
108
- quota-per-wave: 5
109
- confidence-floor: 0.5
110
- auto-dream:
111
- min-confidence: 0.5
112
- cold-start:
113
- enabled: true
114
- nudge-after-hours: 1
115
- silence-after-sessions: 1
116
- state-md-lock:
117
- enabled: true
118
- timeout-ms: 10000
119
- handover-gate:
120
- enabled: true
121
- max-open-questions: 3
122
- issue-budget:
123
- max-per-session: 12
124
- mode: strict
125
- overflow: collect-issue
126
- broken-window-budget:
127
- enabled: false
128
- due-days: 7
129
- slopcheck:
130
- enabled: false
131
- sources: [plan, discovery]
132
- templates-first:
133
- enabled: true
134
- hosts: [github, gitlab]
135
- verification-auto-fix:
136
- enabled: false
137
- max-retries: 2
138
- discovery-validator:
139
- enabled: false
140
- frontend-slop-hook:
141
- enabled: false
142
- loop-guard:
143
- enabled: true
144
- threshold: 3
145
- window: 5
146
- instruction-budget:
147
- enabled: true
148
- ceiling: 480
149
- mode: warn
150
- config-protection:
151
- enabled: true
152
- mode: warn
153
- allow-config-weakening: false
154
- custom-phases:
155
- - name: archive-closed-prds
156
- when: both
157
- command: node scripts/archive-closed-prds.mjs --apply
158
- mode: warn
159
- - name: archive-closed-plans
160
- when: both
161
- command: node scripts/archive-closed-prds.mjs --apply --prd-dir docs/plans --vault-subdir 01-projects/session-orchestrator/plans
162
- mode: warn
163
- remote-hosts:
164
- - alias: m5
165
- roles-allowed: [test, ui, perf]
166
- - alias: m5-remote
167
- roles-allowed: [test, ui, perf]
168
- evolve:
169
- extra-sources: []
170
- dialectic:
171
- cadence: 5
172
- model: haiku
173
- budget-tokens: 32000
174
- eval:
175
- enabled: true
176
- mode: warn
177
- judge: off
178
- report: html
179
- handle:
180
- reconcile:
181
- enabled: false
182
- mode: warn
183
- targets: [repo-local]
184
- rule-expiry-days: null
185
- confidence-floor: 0.5
186
- min-rule-days: 7
187
- min-insight-chars: 24
188
-
189
- ## Skill Evolution <!-- consistency:exempt:parity-exempt-skill-evolution-block -->
190
-
191
- > Opt-in self-evolution autonomy gate (Epic #643). A DISTINCT top-level block from the `evolve:` Session Config key above — `scripts/lib/config/skill-evolution.mjs` parses it independently of the `## Session Config` boundary, so `claude-md-drift-check` Check 6 (session-config-parity) never flags it.
192
- > See `docs/session-config-reference.md` § Skill Evolution for the #652 activation history, the C2/H1-guard detail, and the quadruple-gate + MR-only rules.
193
-
194
- skill-evolution:
195
- autonomy: autonomous-gated # off | advisory | autonomous-gated — armed (#652)
196
- evidence-floor: 0.5 # float 0.0..1.0 — min evidence before an autonomous-gated repair acts
197
- judge: off # opt-in session-end LLM-judge (advisory only); default off
198
-
199
- ## Dispatcher Autonomy <!-- consistency:exempt:parity-exempt-dispatcher-autonomy-block -->
200
-
201
- > **Parity-exempt section** (Epic #673, #679). Intentionally OUTSIDE `## Session Config` so `claude-md-drift-check` Check-6 (session-config-parity) does not flag repos that have not adopted this feature — `scripts/lib/config/dispatcher-autonomy.mjs` parses it independently.
202
- > This block's committed presence is itself the never-re-ask marker (session-start Phase 1.1 migration trigger). Effective autonomy resolves host-locally: env > `owner.yaml` > committed > `off`.
203
- > See `docs/session-config-reference.md` § Dispatcher Autonomy for the #681 capture history and the full precedence chain.
204
-
205
- dispatcher-autonomy:
206
- autonomy: off # off | advisory | autonomous-gated — default off (fail-closed)
207
- confidence-floor: 0.5 # float 0.0..1.0