session-orchestrator 5.2.0 → 5.3.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.
- package/.agents/skills/architecture/SKILL.md +3 -1
- package/.agents/skills/autopilot/SKILL.md +5 -1
- package/.agents/skills/autopilot/agents/openai.yaml +5 -0
- package/.agents/skills/bootstrap/SKILL.md +5 -1
- package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
- package/.agents/skills/brainstorm/SKILL.md +5 -1
- package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +3 -1
- package/.agents/skills/close/SKILL.md +5 -1
- package/.agents/skills/close/agents/openai.yaml +5 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
- package/.agents/skills/debug/SKILL.md +5 -1
- package/.agents/skills/debug/agents/openai.yaml +5 -0
- package/.agents/skills/discovery/SKILL.md +5 -1
- package/.agents/skills/discovery/agents/openai.yaml +5 -0
- package/.agents/skills/dispatcher/SKILL.md +5 -1
- package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ecosystem-health/SKILL.md +3 -1
- package/.agents/skills/eli5/SKILL.md +5 -1
- package/.agents/skills/eli5/agents/openai.yaml +5 -0
- package/.agents/skills/eval/SKILL.md +6 -2
- package/.agents/skills/eval/agents/openai.yaml +5 -0
- package/.agents/skills/evolve/SKILL.md +6 -2
- package/.agents/skills/evolve/agents/openai.yaml +5 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
- package/.agents/skills/gitlab-ops/SKILL.md +3 -1
- package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
- package/.agents/skills/go/SKILL.md +5 -1
- package/.agents/skills/go/agents/openai.yaml +5 -0
- package/.agents/skills/grill/SKILL.md +5 -1
- package/.agents/skills/grill/agents/openai.yaml +5 -0
- package/.agents/skills/harness-audit/SKILL.md +5 -1
- package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
- package/.agents/skills/hook-development/SKILL.md +3 -1
- package/.agents/skills/mcp-builder/SKILL.md +3 -1
- package/.agents/skills/memory-cleanup/SKILL.md +5 -1
- package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.agents/skills/mode-selector/SKILL.md +3 -1
- package/.agents/skills/npm-publish/SKILL.md +4 -2
- package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
- package/.agents/skills/persona-panel/SKILL.md +5 -1
- package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
- package/.agents/skills/plan/SKILL.md +5 -1
- package/.agents/skills/plan/agents/openai.yaml +5 -0
- package/.agents/skills/playwright-driver/SKILL.md +3 -1
- package/.agents/skills/portfolio/SKILL.md +5 -1
- package/.agents/skills/portfolio/agents/openai.yaml +5 -0
- package/.agents/skills/quality-gates/SKILL.md +3 -1
- package/.agents/skills/reconcile/SKILL.md +5 -1
- package/.agents/skills/reconcile/agents/openai.yaml +5 -0
- package/.agents/skills/release/SKILL.md +5 -1
- package/.agents/skills/release/agents/openai.yaml +5 -0
- package/.agents/skills/remote-offload/SKILL.md +3 -1
- package/.agents/skills/repo-audit/SKILL.md +5 -1
- package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
- package/.agents/skills/session/SKILL.md +21 -0
- package/.agents/skills/session/agents/openai.yaml +5 -0
- package/.agents/skills/session-end/SKILL.md +3 -1
- package/.agents/skills/session-plan/SKILL.md +3 -1
- package/.agents/skills/session-start/SKILL.md +3 -1
- package/.agents/skills/spinout/SKILL.md +5 -1
- package/.agents/skills/spinout/agents/openai.yaml +5 -0
- package/.agents/skills/sunset-review/SKILL.md +5 -1
- package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
- package/.agents/skills/templates-ack/SKILL.md +21 -0
- package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
- package/.agents/skills/test/SKILL.md +5 -1
- package/.agents/skills/test/agents/openai.yaml +5 -0
- package/.agents/skills/test-runner/SKILL.md +3 -1
- package/.agents/skills/tmux-layout/SKILL.md +3 -1
- package/.agents/skills/using-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ux-grill/SKILL.md +5 -1
- package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
- package/.agents/skills/vault-mirror/SKILL.md +3 -1
- package/.agents/skills/vault-sync/SKILL.md +3 -1
- package/.agents/skills/wave-executor/SKILL.md +3 -1
- package/.agents/skills/write-executable-plan/SKILL.md +3 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +4 -4
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -3
- package/.codex-plugin/skills/eval/SKILL.md +1 -1
- package/.codex-plugin/skills/evolve/SKILL.md +1 -1
- package/.codex-plugin/skills/npm-publish/SKILL.md +1 -3
- package/.codex-plugin/skills/session/SKILL.md +1 -1
- package/.cursor/commands/eval.md +1 -1
- package/.cursor/commands/session.md +1 -1
- package/.cursor/rules/000-session-orchestrator.mdc +0 -2
- package/.cursor/rules/050-plan.mdc +1 -1
- package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/npm-publish/SKILL.md +1 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.orchestrator/policy/blocked-commands.json +12 -3
- package/AGENTS.md +3 -2
- package/CHANGELOG.md +136 -0
- package/README.md +9 -9
- package/SECURITY.md +12 -0
- package/agents/dialectic-deriver.md +13 -10
- package/agents/eval-judge.md +67 -45
- package/agents/skill-applied-judge.md +34 -19
- package/commands/session.md +7 -3
- package/docs/baseline.md +12 -6
- package/docs/codex-setup.md +14 -2
- package/docs/components.md +7 -5
- package/docs/events-schema.md +56 -9
- package/docs/rule-authoring.md +58 -6
- package/docs/session-config-reference.md +100 -7
- package/docs/session-config-template.md +31 -2
- package/docs/telemetry.md +2 -0
- package/hooks/_lib/hook-import-set.json +85 -8
- package/hooks/_lib/subagent-transcript.mjs +582 -31
- package/hooks/config-protection.mjs +11 -3
- package/hooks/cwd-change-restore.mjs +11 -3
- package/hooks/enforce-commands.mjs +70 -23
- package/hooks/enforce-scope.mjs +143 -33
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +1 -1
- package/hooks/loop-guard.mjs +11 -3
- package/hooks/on-session-end.mjs +58 -23
- package/hooks/on-session-start.mjs +48 -11
- package/hooks/on-stop.mjs +168 -22
- package/hooks/operator-steer.mjs +11 -3
- package/hooks/post-bash-issue-budget-refund.mjs +18 -8
- package/hooks/post-bash-write-verify.mjs +3 -2
- package/hooks/post-edit-import-probe.mjs +17 -9
- package/hooks/post-edit-validate.mjs +13 -5
- package/hooks/post-subagent-discovery-validator.mjs +98 -13
- package/hooks/post-tool-batch-wave-signal.mjs +200 -38
- package/hooks/post-tool-failure-corrective-context.mjs +11 -5
- package/hooks/post-tooluse-frontend-slop.mjs +10 -4
- package/hooks/pre-auq-clarity.mjs +15 -2
- package/hooks/pre-bash-destructive-guard.mjs +80 -9
- package/hooks/pre-bash-issue-budget.mjs +16 -11
- package/hooks/pre-bash-memory-propose-audit.mjs +86 -54
- package/hooks/pre-bash-sessions-ledger-guard.mjs +391 -20
- package/hooks/pre-bash-staging-fence.mjs +335 -31
- package/hooks/pre-bash-templates-first.mjs +19 -14
- package/hooks/pre-task-scope-disjoint.mjs +233 -2
- package/hooks/subagent-telemetry.mjs +15 -19
- package/hooks/wave-scope-commit-guard.mjs +197 -100
- package/monitors/monitors.json +1 -1
- package/output-styles/wave-summary.md +1 -1
- package/package.json +1 -1
- package/pi/prompts/eval.md +1 -1
- package/pi/prompts/session.md +1 -1
- package/rules/README.md +1 -1
- package/rules/opt-in-domain/prompt-caching.md +1 -1
- package/rules/opt-in-stack/backend-data.md +1 -1
- package/rules/opt-in-stack/backend.md +3 -3
- package/rules/opt-in-stack/frontend.md +1 -1
- package/rules/opt-in-stack/security-web.md +3 -3
- package/rules/opt-in-stack/swift.md +1 -1
- package/scripts/autopilot.mjs +23 -2
- package/scripts/backfill-abandoned-sessions.mjs +117 -15
- package/scripts/check-sessions-integrity.mjs +300 -0
- package/scripts/dialectic-deriver.mjs +50 -13
- package/scripts/emit-session.mjs +75 -29
- package/scripts/eval-session.mjs +65 -3
- package/scripts/generate-agents-skills.mjs +102 -29
- package/scripts/generate-cursor-adapter.mjs +61 -16
- package/scripts/lib/agent-status.mjs +2 -31
- package/scripts/lib/auq/clarity.mjs +10 -2
- package/scripts/lib/auq/parse.mjs +12 -31
- package/scripts/lib/auq/schema.mjs +56 -41
- package/scripts/lib/auto-dialectic.mjs +304 -15
- package/scripts/lib/autopilot/flags.mjs +12 -1
- package/scripts/lib/autopilot/kill-switches.mjs +6 -3
- package/scripts/lib/autopilot/loop.mjs +14 -1
- package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
- package/scripts/lib/ci-status-banner.mjs +376 -16
- package/scripts/lib/command-blocker.mjs +275 -28
- package/scripts/lib/config/dialectic.mjs +12 -3
- package/scripts/lib/config/gate.mjs +74 -0
- package/scripts/lib/config/reaper.mjs +162 -0
- package/scripts/lib/config.mjs +14 -0
- package/scripts/lib/convergence-monitor.mjs +74 -11
- package/scripts/lib/ecosystem-health.mjs +11 -0
- package/scripts/lib/eval/engine.mjs +421 -53
- package/scripts/lib/eval/judge.mjs +463 -40
- package/scripts/lib/eval/schema.mjs +10 -1
- package/scripts/lib/events-rotation.mjs +221 -25
- package/scripts/lib/events-schema.mjs +114 -0
- package/scripts/lib/events.mjs +524 -5
- package/scripts/lib/frontmatter-guard.mjs +21 -10
- package/scripts/lib/gates/gate-baseline.mjs +27 -2
- package/scripts/lib/gates/gate-full.mjs +28 -3
- package/scripts/lib/gates/gate-helpers.mjs +243 -21
- package/scripts/lib/gates/gate-incremental.mjs +28 -3
- package/scripts/lib/gates/gate-per-file.mjs +27 -2
- package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
- package/scripts/lib/instruction-budget-guard.mjs +146 -4
- package/scripts/lib/io.mjs +42 -8
- package/scripts/lib/issue-close-strip-labels.mjs +207 -49
- package/scripts/lib/js-mask.mjs +197 -0
- package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
- package/scripts/lib/maintenance-due-banner.mjs +53 -88
- package/scripts/lib/orphan-reaper.mjs +1588 -0
- package/scripts/lib/peer-cards/merger.mjs +48 -10
- package/scripts/lib/peer-cards/reader.mjs +78 -2
- package/scripts/lib/process-group.mjs +899 -0
- package/scripts/lib/quality-gate.mjs +107 -28
- package/scripts/lib/reconcile/backlog.mjs +368 -0
- package/scripts/lib/reconcile/engine.mjs +55 -188
- package/scripts/lib/reconcile/rule-expiry-sweep.mjs +302 -60
- package/scripts/lib/reconcile/sanitize.mjs +69 -3
- package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
- package/scripts/lib/resource-probe/parsers.mjs +31 -0
- package/scripts/lib/rule-loader.mjs +41 -12
- package/scripts/lib/scope-echo.mjs +39 -2
- package/scripts/lib/scope-gate.mjs +605 -1
- package/scripts/lib/session-close-backfill.mjs +33 -6
- package/scripts/lib/session-id.mjs +9 -20
- package/scripts/lib/session-invocation.mjs +20 -0
- package/scripts/lib/session-schema/constants.mjs +30 -2
- package/scripts/lib/session-schema/normalizer.mjs +56 -4
- package/scripts/lib/session-schema.mjs +8 -3
- package/scripts/lib/session-start-probes.mjs +95 -10
- package/scripts/lib/sessions-canonical.mjs +23 -0
- package/scripts/lib/sessions-integrity-banner.mjs +7 -1
- package/scripts/lib/sessions-staleness-banner.mjs +193 -51
- package/scripts/lib/skill-evidence-window.mjs +891 -0
- package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
- package/scripts/lib/skill-evolution/engine.mjs +18 -9
- package/scripts/lib/skill-judge.mjs +45 -3
- package/scripts/lib/tail-window.mjs +56 -0
- package/scripts/lib/telemetry/schema.mjs +30 -0
- package/scripts/lib/telemetry/sync.mjs +61 -6
- package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
- package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +72 -13
- package/scripts/lib/user-invocable-skills.mjs +23 -3
- package/scripts/lib/ux-grill/reconcile.mjs +48 -22
- package/scripts/lib/validate/check-agents-skills.mjs +26 -15
- package/scripts/lib/validate/check-cursor-adapter.mjs +1 -0
- package/scripts/lib/validate/check-entry-guard.mjs +13 -50
- package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
- package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
- package/scripts/lib/validate/check-rules.mjs +7 -5
- package/scripts/lib/validate/check-skill-links.mjs +9 -1
- package/scripts/lib/validate/check-skill-script-paths.mjs +239 -27
- package/scripts/lib/validate/check-test-git-config-target.mjs +24 -34
- package/scripts/lib/validate/check-untracked-test-deps.mjs +7 -102
- package/scripts/lib/validate/check-unwired-features.mjs +130 -27
- package/scripts/lib/validate/check-validator-registration.mjs +34 -10
- package/scripts/lib/validate/confidential-names.mjs +10 -0
- package/scripts/lib/validate-vendored-rules.mjs +4 -3
- package/scripts/lib/vault-mirror/namespace.mjs +46 -8
- package/scripts/lib/vault-mirror/process.mjs +10 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
- package/scripts/lib/vault-status/narrative-mirror.mjs +31 -7
- package/scripts/lib/vault-yaml.mjs +118 -0
- package/scripts/lib/worktree/lifecycle.mjs +153 -1
- package/scripts/release-session-lock.mjs +305 -0
- package/scripts/release.mjs +30 -5
- package/scripts/resolve-session-invocation.mjs +59 -0
- package/scripts/run-quality-gate.mjs +156 -17
- package/scripts/sweep-expired-rules.mjs +14 -3
- package/scripts/validate-plugin.mjs +12 -0
- package/scripts/validate-wave-scope.mjs +32 -105
- package/scripts/vault-mirror.mjs +9 -1
- package/skills/_shared/platform-tools.md +23 -11
- package/skills/autopilot/SKILL.md +22 -7
- package/skills/claude-md-drift-check/SKILL.md +1 -1
- package/skills/convergence-monitoring/README.md +8 -1
- package/skills/convergence-monitoring/SIGNALS.md +50 -6
- package/skills/convergence-monitoring/SKILL.md +15 -6
- package/skills/eval/SKILL.md +39 -24
- package/skills/eval/rubric-v1.md +1 -0
- package/skills/eval/rubric-v2.md +457 -0
- package/skills/evolve/SKILL.md +1 -1
- package/skills/evolve/references/evolve-dialectic-mode.md +42 -25
- package/skills/gitlab-ops/SKILL.md +3 -2
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +11 -0
- package/skills/session-end/SKILL.md +13 -16
- package/skills/session-end/discovery-scan.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +55 -9
- package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
- package/skills/session-end/session-metrics-write.md +10 -0
- package/skills/session-plan/SKILL.md +17 -5
- package/skills/session-plan/references/session-plan-task-classification.md +2 -2
- package/skills/session-start/references/phase-4-ssot-environment-check.md +2 -1
- package/skills/ux-grill/SKILL.md +1 -1
- package/skills/wave-executor/SKILL.md +8 -4
- package/skills/wave-executor/circuit-breaker.md +2 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +5 -3
- package/skills/wave-executor/references/wave-loop-dispatch.md +2 -1
- package/.codex-plugin/skills/convergence-monitoring/agents/openai.yaml +0 -5
- package/.codex-plugin/skills/npm-publish/agents/openai.yaml +0 -5
- package/.cursor/commands/convergence-monitoring.md +0 -13
- package/.cursor/commands/npm-publish.md +0 -13
- package/pi/prompts/convergence-monitoring.md +0 -11
- package/pi/prompts/npm-publish.md +0 -11
|
@@ -394,6 +394,17 @@ consolidation survives the next `/reconcile`:
|
|
|
394
394
|
regenerates that learning as a standalone file on the next run.
|
|
395
395
|
- **A merged file's `expires-at` is the EARLIEST of its parts**, never the
|
|
396
396
|
latest: it must not outlive its shortest-lived content.
|
|
397
|
+
- **An EXPIRED file no longer dedupes** (#1387): the provenance reader skips it
|
|
398
|
+
whole, so its learnings become re-proposable — fail-open on an unparseable
|
|
399
|
+
date. Two known limits, measured 2026-09-18: this is the on-disk half only
|
|
400
|
+
(79 of this repo's 92 provenance keys are ALSO sidecar-terminal, so just 13
|
|
401
|
+
return), and a file the sweep cannot split or cannot read
|
|
402
|
+
(`no-1to1-mapping`, `no-provenance-block`, `unreadable`, and since GH#70
|
|
403
|
+
`no-counter-sentence` — the fail-closed branch that touches such a file not
|
|
404
|
+
at all, deletion included; none in the live tree today, `skipped: []` over 7
|
|
405
|
+
files) that expires legitimately
|
|
406
|
+
re-proposes on every run with no mechanical exit. Detail:
|
|
407
|
+
`docs/rule-authoring.md` § Consolidated rules.
|
|
397
408
|
- **A dropped learning must be STAMPED before deletion, or it regenerates.**
|
|
398
409
|
`rm .claude/rules/<slug>.md` alone leaves `isProcessed()` false and no
|
|
399
410
|
on-disk marker, so the engine re-proposes it. Stamp it terminal first with
|
|
@@ -151,23 +151,20 @@ discipline as `createSpiralCarryoverIssue`).
|
|
|
151
151
|
|
|
152
152
|
> Gate: Only run if `persistence` is `true` in Session Config. Skip silently otherwise.
|
|
153
153
|
|
|
154
|
-
After STATE.md is finalized with `status: completed` (Phase 3.4) and Recommendations are written (Phase 3.7a), release the distributed session-lock
|
|
154
|
+
After STATE.md is finalized with `status: completed` (Phase 3.4) and Recommendations are written (Phase 3.7a), release the distributed session-lock with ONE verifying command:
|
|
155
155
|
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
// sessionId is the physical raw value established by session-start Phase 1.2
|
|
159
|
-
// and stored in .orchestrator/session.lock `session_id`. It is not STATE.md
|
|
160
|
-
// `session:` or `semantic_session_id`, both of which are attribution labels.
|
|
161
|
-
const rawSessionId = sessionId;
|
|
162
|
-
const result = release({ sessionId: rawSessionId, repoRoot: process.cwd() });
|
|
163
|
-
// result.ok is always true unless a filesystem error occurred.
|
|
164
|
-
// result.deleted === true → lock file removed successfully.
|
|
165
|
-
// result.deleted === false → lock was absent or had a different raw session_id.
|
|
156
|
+
```bash
|
|
157
|
+
node scripts/release-session-lock.mjs --session-id "<raw session_id>" --json
|
|
166
158
|
```
|
|
167
159
|
|
|
168
|
-
|
|
160
|
+
`--session-id` is the PHYSICAL raw value established by session-start Phase 1.2 and stored in `.orchestrator/session.lock` `session_id` — never STATE.md `session:` and never `semantic_session_id`, both of which are attribution labels.
|
|
161
|
+
|
|
162
|
+
The command releases the lock only when that raw id owns it, emits the terminal `orchestrator.session.lock.released` breadcrumb, and then RE-READS the lock path: **exit 0 means the lock is provably gone.** It replaces the hand-executed `release()` this phase used to prescribe, which deleted the lock silently — the SessionEnd hook then found `status: 'absent'` and emitted nothing either, so a lock lifecycle ended with no terminal event at all (#1395: 5 `lock.acquired` against 0 `lock.released` in this repo). `outcome: "absent"` is a normal exit-0 result (idempotent re-run; nothing was released, so no event is written).
|
|
163
|
+
|
|
164
|
+
A non-zero exit is a WARN, never a blocker — log `⚠ session-lock: <outcome>` and continue; the TTL provides automatic expiry for the next session:
|
|
169
165
|
|
|
170
|
-
|
|
166
|
+
- **exit 1** — the lock is owned by a different raw session id, so nothing was touched. That is ambiguous by design: do **not** retry with an equal `semantic_session_id`, STATE.md `session`, or owner proof. Leave that live lock for its TTL/Reaper lifecycle.
|
|
167
|
+
- **exit 2** — system error (unreadable/corrupt lock, owner-proof mismatch, the lock still present after release, or the breadcrumb could not be written).
|
|
171
168
|
|
|
172
169
|
The lock is released here — AFTER all STATE.md writes are complete and BEFORE the commit is staged in Phase 4.1. This ordering ensures a clean handover when the current raw owner releases it: the lock file is absent from the working tree when the commit is assembled, so it is not accidentally staged.
|
|
173
170
|
|
|
@@ -260,7 +257,7 @@ swallow it with `|| true`.
|
|
|
260
257
|
|
|
261
258
|
## Phase 5: Issue Cleanup
|
|
262
259
|
|
|
263
|
-
> Always runs. Closes resolved issues (
|
|
260
|
+
> Always runs. Closes resolved issues via the single `node "$PLUGIN_ROOT/scripts/lib/issue-close-strip-labels.mjs" --close [--vcs gitlab|github] [-R <spec>] <id>...` CLI call (strips `status:*` labels, closes, then re-reads each id; a `closed: false` in its per-id JSON output is a finding, not done — #308), updates partially-done issues, and in Step 3 FILES the Phase 1.65 gate's carry-list — the deferred `createSpiralCarryoverIssue` call for SPIRAL/FAILED items and the `markOpenQuestionAnsweredOnDisk` write live here, not in Phase 1.65 (atomicity). Step 3b folds non-exempt over-cap creations into one `[Backlog-Sammel]` collector under the `issue-budget` cap; discovery findings from Phase 1.5 are filed at the end. Full procedure: [`references/phase-5-issue-cleanup.md`](references/phase-5-issue-cleanup.md).
|
|
264
261
|
|
|
265
262
|
## Phase 6: Final Report
|
|
266
263
|
|
|
@@ -280,7 +277,7 @@ Present to the user the **Session Summary**: Completed / Carried Over / Dropped
|
|
|
280
277
|
| `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 |
|
|
281
278
|
| `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 |
|
|
282
279
|
| `learning-patterns.md` | Phases 3.5a + 3.6 extraction heuristics, confidence updates, passive decay, and JSONL write procedure |
|
|
283
|
-
| `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 — `runSkillJudge
|
|
280
|
+
| `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 |
|
|
284
281
|
| `scripts/lib/session-end/phase-skip.mjs` | Phase 3.6.x tail skip-plan aggregator (#724) — `planTailPhases({repoRoot, config, sessionId, platform})` → `{plan, skippedReport}`; side-effect-free (reconcile/sweep via dry-run — no writes), never-throws (per-phase probe error fail-opens to `run: true`). Since 2026-09-09 it plans FOUR phases, not six: the 3.6.5 (auto-dream) and 3.6.7 (auto-dialectic) deciders were removed with those phases' retirement. Its APPLY half for 3.6.4 is `scripts/lib/session-end/tail-runner.mjs` (`runTailPhases`, `runExpiredSweep`) — the planner fails OPEN, the runner fails CLOSED |
|
|
285
282
|
| `references/phase-3-documentation-updates.md` § 3.45 | Telemetry Flush (advisory, #844; MECHANICAL since #1138 — `hooks/on-session-end.mjs` calls `flush()` itself at the end of every teardown and emits an `orchestrator.telemetry.flush` breadcrumb, so this phase is the DESCRIPTION and the fallback, never the trigger; a coordinator that skips it changes nothing) — `flush()` from `scripts/lib/telemetry/sync.mjs` drains the host-local send-queue fire-and-forget; no config key (send-gate is `resolveConsent()` inside the module, fail-closed); skip when `persistence: false`; never-throw + ~3s-bounded, offline → bounded oldest-dropped queue, optional `Telemetry: sent/queued/gated` close-summary line, NEVER an error banner; runs late in the close after Phase 3.7 |
|
|
286
283
|
| `session-metrics-write.md` | Phase 3.7 JSONL append, vault-mirror invocation, durable narrative mirror (`mirrorNarrative`, #675), and behavior matrix |
|
|
@@ -292,7 +289,7 @@ Present to the user the **Session Summary**: Completed / Carried Over / Dropped
|
|
|
292
289
|
| (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) |
|
|
293
290
|
| `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 |
|
|
294
291
|
| `references/phase-4b-worktree-orphan-sweep.md` | Phase 4b full procedural body — `checkWorktreeOrphans()` read-only proposal set, the coordinator-rendered AUQ, opt-in `worktree-orphans.enabled` gate |
|
|
295
|
-
| `references/phase-5-issue-cleanup.md` | Phase 5 full procedural body — close resolved issues (`
|
|
292
|
+
| `references/phase-5-issue-cleanup.md` | Phase 5 full procedural body — close resolved issues via `node "$PLUGIN_ROOT/scripts/lib/issue-close-strip-labels.mjs" --close` (strip `status:*` → close → re-read; `closed: false` is a finding, not done, #308), Step 3 filing of the Phase 1.65 carry-list incl. the deferred `createSpiralCarryoverIssue` and `markOpenQuestionAnsweredOnDisk`, Step 3b `[Backlog-Sammel]` overflow, discovery-issue creation |
|
|
296
293
|
| `references/phase-5-issue-cleanup.md` § Step 3b.2 (issue-budget reconcile) | Phase 5 issue-budget cross-check — `reconcileIssueBudget({ repoRoot, record, sessionId, rawSessionId, config })` from `scripts/lib/issue-budget-reconcile.mjs` runs on the in-memory session record BEFORE it is appended to `sessions.jsonl`, `emitIssueBudgetReconciled` records `orchestrator.issue_budget.reconciled`, and `formatIssueBudgetReconcileWarn(result)` prints the verdict (`match` / `no-ledger` / `escaped` / `stale-record`) in the Final Report. Ordered AFTER the overflow drain (which resets `overflow[]`) and BEFORE `reapStaleBudgetFiles` (which must not remove the file being read) |
|
|
297
294
|
| `references/session-summary-template.md` | Phase 6 Final Report — the full Session Summary template (Completed / Carried Over / Dropped at Handover Gate / New Issues / Unresolved Review Findings / Metrics incl. Docs Health + Custom Phases / Next Session Recommendations) plus the Test-delta and Documentation-Coverage anchors |
|
|
298
295
|
|
|
@@ -27,7 +27,7 @@ Agent({
|
|
|
27
27
|
run_in_background: false
|
|
28
28
|
})
|
|
29
29
|
```
|
|
30
|
-
|
|
30
|
+
Use the native delegation tools actually exposed by the current runtime, following [Platform Tool Adaptation](../_shared/platform-tools.md). If the runtime exposes no suitable delegation tool, execute the probes sequentially within the current context.
|
|
31
31
|
- Collect verified findings from the discovery output
|
|
32
32
|
- Parse the discovery output for the **findings** array and **stats** object (see Parsing callout below)
|
|
33
33
|
- Store the stats object for Phase 1.7 metrics collection (`discovery_stats` field)
|
|
@@ -178,29 +178,75 @@ After learnings are written (Phase 3.6), and when the judge is enabled, run a **
|
|
|
178
178
|
|
|
179
179
|
1. Read `config['skill-evolution'].judge` (default `false`), `config['skill-evolution']['judge-budget-tokens']` (default 8000), and `persistence`. Apply the two skip gates above.
|
|
180
180
|
|
|
181
|
-
2. Determine the **judged set** — only THIS session's selected skills.
|
|
181
|
+
2. Determine the **judged set** — only THIS session's selected skills.
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
> **Join on the RAW UUID, never on the semantic session id.** The writer is the `PreToolUse` hook `hooks/skill-invocation-telemetry.mjs`, which stamps `session_id` straight from the hook payload (`:190`) — that is the harness UUID. Measured 2026-09-19 over `.orchestrator/metrics/skill-invocations.jsonl` (841 lines): **767 raw UUIDs, 55 semantic ids, 17 null**. Joining on `main-<date>-session-N` therefore matches ~0 rows for a current session, the judged set comes back empty, and the phase reports `empty-input` — a silent no-op indistinguishable from "this session used no skills". The raw id is `process.env.CLAUDE_CODE_SESSION_ID` (or `session_id` of a live `.orchestrator/session.lock`); it is also the id that names the transcript file in step 3.
|
|
184
184
|
|
|
185
185
|
```javascript
|
|
186
|
-
import {
|
|
186
|
+
import { readFileSync } from 'node:fs';
|
|
187
|
+
import { readLock } from '${PLUGIN_ROOT}/scripts/lib/session-lock.mjs';
|
|
188
|
+
|
|
189
|
+
const rawSessionId =
|
|
190
|
+
(process.env.CLAUDE_CODE_SESSION_ID || '').trim() ||
|
|
191
|
+
(readLock({ repoRoot: process.cwd() })?.session_id || '').trim();
|
|
192
|
+
|
|
193
|
+
const selectedSkills = [...new Set(
|
|
194
|
+
readFileSync('.orchestrator/metrics/skill-invocations.jsonl', 'utf8')
|
|
195
|
+
.split('\n').filter(Boolean)
|
|
196
|
+
.flatMap((l) => { try { return [JSON.parse(l)]; } catch { return []; } })
|
|
197
|
+
.filter((r) => r.session_id === rawSessionId && typeof r.skill === 'string')
|
|
198
|
+
.map((r) => r.skill),
|
|
199
|
+
)];
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
If the judged set is empty, `runSkillJudge` returns `status: 'empty-input'` (no dispatch) — log and continue.
|
|
203
|
+
|
|
204
|
+
3. **Build the evidence window, then invoke `runSkillJudge`.** This is ONE verifying call, not a prose instruction: before #1399 this step named a free variable `transcriptTail` that nothing in the tree produced, so the judge was dispatched with an EMPTY `<untrusted-data-…>` fence. Measured 2026-09-19 at `8f15f77b`: such a prompt is 1387 characters = 346 estimated tokens, well under the 8000-token budget, so the budget gate never caught it — the judge ruled on a transcript it had never seen.
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
import { buildSkillEvidence } from '${PLUGIN_ROOT}/scripts/lib/skill-evidence-window.mjs';
|
|
208
|
+
import { runSkillJudge, evidenceBudgetChars } from '${PLUGIN_ROOT}/scripts/lib/skill-judge.mjs';
|
|
187
209
|
import { appendSkillJudgment } from '${PLUGIN_ROOT}/scripts/lib/skill-judgments-schema.mjs';
|
|
188
210
|
import path from 'node:path';
|
|
189
211
|
|
|
190
212
|
const budgetTokens = config['skill-evolution']['judge-budget-tokens'] ?? 8000;
|
|
213
|
+
const budget = { input: budgetTokens, output: 4000 };
|
|
214
|
+
|
|
215
|
+
// `buildSkillEvidence` resolves ~/.claude/projects/<encoded-repo>/<rawSessionId>.jsonl,
|
|
216
|
+
// locates each skill's invocation anchors and renders bounded excerpts. Never throws.
|
|
217
|
+
const evidence = await buildSkillEvidence({
|
|
218
|
+
repoRoot: process.cwd(),
|
|
219
|
+
sessionId: rawSessionId, // RAW UUID — it names the transcript FILE
|
|
220
|
+
skills: selectedSkills,
|
|
221
|
+
budgetChars: evidenceBudgetChars(selectedSkills, budget),
|
|
222
|
+
includeSubagents: true, // #1412 — see the note below
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// VERIFY before dispatching — these three numbers are the receipt for this step.
|
|
226
|
+
console.error(
|
|
227
|
+
`skill-judge: evidence ${evidence.status} — ${evidence.chars} chars from ` +
|
|
228
|
+
`${evidence.source.records} records (${evidence.source.malformed_lines} malformed), ` +
|
|
229
|
+
`skipped: ${JSON.stringify(evidence.skipped)}`,
|
|
230
|
+
);
|
|
231
|
+
|
|
191
232
|
const result = await runSkillJudge({
|
|
192
233
|
// Claude Code path: wire the real read-only haiku subagent as dispatchAgent.
|
|
193
234
|
dispatchAgent: ({ model, prompt, maxTokens }) =>
|
|
194
235
|
Agent({ subagent_type: 'skill-applied-judge', model: 'haiku', prompt, max_tokens: maxTokens }),
|
|
195
236
|
repoRoot: process.cwd(),
|
|
196
|
-
sessionId,
|
|
197
|
-
|
|
237
|
+
sessionId: rawSessionId,
|
|
238
|
+
evidence, // UNTRUSTED excerpts — fenced by the lib
|
|
198
239
|
selectedSkills, // distinct skills from step 2
|
|
199
240
|
model: 'haiku',
|
|
200
|
-
budget
|
|
241
|
+
budget,
|
|
201
242
|
});
|
|
202
243
|
```
|
|
203
244
|
|
|
245
|
+
- `evidence.status` is `no-transcript` (no file for this session id) or `no-evidence` (file read, no invocation anchor found) or `ok`. On the first two the evidence text is `''` and `runSkillJudge` returns `status: 'no-evidence'` **without dispatching** — log and continue, never fabricate a tail to get past it.
|
|
246
|
+
- `evidence.source.malformed_lines > 0` means the window is a PARTIAL read of the transcript. Log it beside the judgment; a clean verdict over an incompletely-read input is the failure this field exists to expose.
|
|
247
|
+
- `evidence.truncated === true` or a non-empty `evidence.skipped` means some judged skill got no excerpt — the judge will correctly answer `unknown` for it.
|
|
248
|
+
- **`includeSubagents: true` is set HERE, not in the library (#1412).** `buildSkillEvidence`'s own default stays `false`, so every other caller keeps the fail-closed behaviour and this one choice is greppable. Without it, a skill dispatched INSIDE a subagent (`<uuid>/subagents/agent-*.jsonl`) has no anchor in the main transcript, the phase reports `no-evidence`, and the reach limit is invisible — `runSkillJudge` correctly does not dispatch, so nothing is mis-judged, but nothing is ever judged either. Cost measured 2026-09-20 over the 3 most recent sessions carrying a `subagents/` dir: records 4.2-5.0x, read time 22 → 175 ms, window size still far under budget.
|
|
249
|
+
- The extra records are bounded two ways, both inside `renderEvidence`: subagent-only skills share at most `DEFAULT_SUBAGENT_POOL_SHARE` (0.25) of the per-skill pool whenever coordinator-anchored skills are also present, and the shared `### session closing` excerpt is taken from the MAIN transcript's tail (`mainRecordCount`), never from the last subagent file that happens to sit at the end of the concatenated array. Anything that still does not fit is reported in `evidence.skipped` with `truncated: true` — never silently shortened.
|
|
204
250
|
- **Claude Code path:** `dispatchAgent` wraps the real `Agent({ subagent_type: 'skill-applied-judge', model: 'haiku', … })`. The agent is `sandbox-tier: read-only` and RETURNS one fenced ```json block — it never writes files.
|
|
205
251
|
- **Codex / Cursor path:** there is no subagent type. Wire `dispatchAgent` as a coordinator-inline call (the coordinator itself reasons over the prompt and returns `{ text }`), keeping the identical `runSkillJudge` signature. Same DI seam, no harness subagent.
|
|
206
252
|
|
|
@@ -221,16 +267,16 @@ After learnings are written (Phase 3.6), and when the judge is enabled, run a **
|
|
|
221
267
|
|
|
222
268
|
`appendSkillJudgment` re-validates each record; `advisory !== true` is schema-rejected, so a tampered record can never be persisted.
|
|
223
269
|
|
|
224
|
-
5. On `result.status === 'empty-input'` or `'budget-exceeded'`: log the status (e.g. `skill-judge: skipped (budget-exceeded used=N budget=M)`) and continue. No sidecar write on
|
|
270
|
+
5. On `result.status === 'empty-input'`, `'no-evidence'` or `'budget-exceeded'`: log the status (e.g. `skill-judge: skipped (budget-exceeded used=N budget=M)`, `skill-judge: skipped (no-evidence — ${result.skipped_reason})`) and continue. No sidecar write on any non-ok status, and no dispatch happened on any of them.
|
|
225
271
|
|
|
226
272
|
6. **Failures are non-fatal.** Any error from the dispatch or write is logged to `.orchestrator/metrics/sweep.log` and the close continues — same posture as Phase 3.6.7. The judge is advisory; a failed judgment must never block session close.
|
|
227
273
|
|
|
228
|
-
Cross-reference: PRD §A L3 acceptance criteria (#645, epic #643); `scripts/lib/skill-judge.mjs` API (`runSkillJudge`, `validateModel`, `estimateInputTokens`, `checkBudget`, `buildJudgePrompt`, `parseJudgeResponse`); `scripts/lib/skill-judgments-schema.mjs` (`appendSkillJudgment`, `readSkillJudgments`, `validateSkillJudgment`); agent `agents/skill-applied-judge.md`.
|
|
274
|
+
Cross-reference: PRD §A L3 acceptance criteria (#645, epic #643); issue #1399 (the evidence producer + the raw-UUID join); `scripts/lib/skill-evidence-window.mjs` API (`buildSkillEvidence`, `locateSkillAnchors`, `renderEvidence`, `readTranscriptRecords`, `resolveRawSessionId`); `scripts/lib/skill-judge.mjs` API (`runSkillJudge`, `validateModel`, `estimateInputTokens`, `checkBudget`, `buildJudgePrompt`, `evidenceBudgetChars`, `parseJudgeResponse`); `scripts/lib/skill-judgments-schema.mjs` (`appendSkillJudgment`, `readSkillJudgments`, `validateSkillJudgment`); agent `agents/skill-applied-judge.md`.
|
|
229
275
|
|
|
230
276
|
### 3.6.7 Auto-Dialectic Dispatch (#506, F2.5) — RETIRED
|
|
231
277
|
|
|
232
278
|
> **RETIRED 2026-09-09.** The nudge is replaced by the session-start `maintenance-due` probe (`checkMaintenanceDue`, `scripts/lib/maintenance-due-banner.mjs`), whose `dialectic` signal reads the side-effect-free `shouldDispatchAutoDialectic` — never a variant that advances the last-run stamp, which would consume the very signal it reports. Its decider is also gone from `planTailPhases()` in `scripts/lib/session-end/phase-skip.mjs`; the heading stays because other docs cite it.
|
|
233
|
-
> The housekeeping session runs `/evolve dialectic` itself (see `skills/session-start/SKILL.md` Phase 7 — the maintenance loop): dry-run first, review `.orchestrator/dialectic-pending.md`, then apply. `
|
|
279
|
+
> The housekeeping session runs `/evolve dialectic` itself (see `skills/session-start/SKILL.md` Phase 7 — the maintenance loop): dry-run first, review `.orchestrator/dialectic-pending.md`, then apply. On that manual path the read-only `dialectic-deriver` agent is dispatched, and `/evolve dialectic` Step 6.4 closes the loop after a successful `--apply` or an explicit discard by calling `writeDialecticLastRun` and `consumeDialecticPending` from `scripts/lib/auto-dialectic.mjs` (`skills/evolve/references/evolve-dialectic-mode.md`); `shouldDispatchAutoDialectic` is read only by the session-start maintenance-due probe. The recording wrapper around that signal, and its `orchestrator.dialectic.nudge_decided` event, were removed in #1288 — nothing emits that event any more. <!-- path-check: example -->
|
|
234
280
|
|
|
235
281
|
> **Dialectic chain rationale** — design choices in the manual `/evolve --dialectic` chain (`/evolve → runDialecticDeriver → dispatchAgent → Agent`). Session-end no longer auto-dispatches this chain (see #614 — the `evolve` agent never existed); the rationale below applies when you run `/evolve --dialectic` manually:
|
|
236
282
|
> - **/evolve → subagent (not direct invoke):** the manual `/evolve --dialectic` skill spawns a subagent so the dialectic pass runs in a fresh context window — keeping the deriver's input-heavy payload (top-50 learnings + last-10 sessions + 2 peer cards + steering) out of the invoking coordinator's context, and letting the deriver run as Haiku while the coordinator stays Opus.
|
|
@@ -6,22 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
> **VCS Reference:** Use CLI commands per the "Common CLI Commands" section of the gitlab-ops skill.
|
|
8
8
|
|
|
9
|
-
1. **Close resolved issues
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// For each resolved issue IID:
|
|
15
|
-
const { stripped, error } = await stripStatusLabels({ issueId: iid, vcs: '<from Session Config>' });
|
|
16
|
-
if (error) {
|
|
17
|
-
console.warn(`⚠ label strip failed for #${iid}: ${error} — proceeding with close`);
|
|
18
|
-
} else if (stripped.length) {
|
|
19
|
-
console.log(`Stripped ${stripped.join(', ')} from #${iid}`);
|
|
20
|
-
}
|
|
21
|
-
// then: glab issue close <iid> / gh issue close <iid>
|
|
9
|
+
1. **Close resolved issues — one command strips, closes and verifies (#308):** run the CLI ONCE with every resolved issue ID, `--vcs` taken from Session Config:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node "$PLUGIN_ROOT/scripts/lib/issue-close-strip-labels.mjs" --close --vcs <gitlab|github> <iid> [<iid> ...]
|
|
22
13
|
```
|
|
23
14
|
|
|
24
|
-
|
|
15
|
+
For each ID, in this order, it strips every `status:*` label (a closed issue carrying `status:in-progress` or `status:ready` skews dashboard filters and discovery heuristics), closes the issue, then re-reads it. It prints one JSON line per ID — `{"id","stripped","closed","state"}`, plus `stripError` / `error` when a step failed — and exits 1 when any ID did not verify as closed. Pass `-R <spec>` only to override the repo; without it the repo resolves from the git remotes (#839). Do not hand-roll `stripStatusLabels` + `glab issue close` instead: that two-step prose path was skipped often enough that 339 closed issues still carried `status:in-progress` (measured 2026-09-19).
|
|
16
|
+
|
|
17
|
+
**Read the JSON, not just the exit code.** `closed: true` means the platform itself reported `state: closed` on the re-read. Every line with `closed: false` is a finding for the Phase 6 Final Report, quoting its `error`. Never report that issue as done. Stripping is non-fatal: a failed strip is printed to stderr, recorded as `stripError`, and the close still runs. List those IDs in the Final Report so the label can be removed by hand. Stripping is idempotent: an issue without `status:*` labels gets no update call.
|
|
18
|
+
|
|
19
|
+
Then add the closing note per issue with the note command from the "Common CLI Commands" section of the gitlab-ops skill (the CLI posts no notes).
|
|
25
20
|
|
|
26
21
|
2. **Update in-progress issues**: ensure labels reflect actual state using the issue update command
|
|
27
22
|
3. **Create carryover issues — from the Phase 1.65 gate's carry-list ONLY (#769):** file an issue for each item on the carry-list produced by the Handover Alignment Gate — i.e. the non-deselectable **auto-carry** class (`priority::critical|high`, SPIRAL/FAILED, or no-origin-issue candidates) PLUS the middle-band items the operator LEFT SELECTED in triage. Do NOT file anything the gate dropped, and do NOT file directly from Phase 1.2/1.3/1.4/1.6 — those phases only collected candidates.
|
|
@@ -120,6 +120,16 @@
|
|
|
120
120
|
echo "ERROR: last sessions.jsonl line is not valid JSON — manual fix required" >&2; exit 1;
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
|
+
|
|
124
|
+
4a. **Verify the record SCHEMA, not just its JSON syntax (#1408)** — step 4 only proves the line parses. The #1408 record parsed fine and was still invalid (`ended_at` instead of `completed_at`, four required fields missing, wave objects keyed `n` instead of `wave`); `vault-mirror` dropped it as `skipped-invalid`, so that session got no vault note and nobody was told until the NEXT session-start banner. Run the same check `/close`'s successor would run, now:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
node "$PLUGIN_ROOT/scripts/check-sessions-integrity.mjs" --session-id "$SESSION_ID" || exit 1
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Exit contract:** 0 = this session's record validates and mirrors. 1 = THIS session's record is broken, or is not in the ledger at all — block the close and re-emit via `scripts/emit-session.mjs`. 2 = tool error (bad flag, unreadable repo root). Pre-existing invalid records from earlier sessions are printed (the banner text on stderr) but never block: they are not this close's to fix, and failing on them would make every close red until someone ran `node scripts/repair-invalid-sessions.mjs --apply`. Identity (`--session-id`), not tail POSITION, is the filter — a parallel session may append between step 2 and here. A named id with NO record fails on purpose: "sound" and "never written" are indistinguishable to the checker, and passing on that reading is the fail-open half.
|
|
131
|
+
|
|
132
|
+
Add `--repo-root <path>` when the cwd is not the repo (the default is cwd), and `--json` for a machine-readable result (`{ok, exitCode, sessionId, matched, findings[]}`).
|
|
123
133
|
5. **Vault Mirror** — mirror the session entry to the Obsidian vault (if configured):
|
|
124
134
|
|
|
125
135
|
```bash
|
|
@@ -42,6 +42,7 @@ Transform the agreed session scope (from session-start Q&A) into an executable w
|
|
|
42
42
|
This skill receives the agreed session scope from session-start. The scope includes:
|
|
43
43
|
- **Issue list**: VCS issue numbers and titles selected by the user
|
|
44
44
|
- **Session type**: housekeeping, feature, or deep
|
|
45
|
+
- **Task context and execution request**: preserve the user's request for parallel agents or waves, if present; it is considered before either housekeeping shortcut below.
|
|
45
46
|
- **Recommended focus**: the option the user selected in session-start Phase 7
|
|
46
47
|
- **Session Config**: parsed JSON from `parse-config.mjs`
|
|
47
48
|
- **Express-path signal** (optional): session-start Phase 8.5 may set `EXPRESS_PATH=true` in the handoff context when the activation conditions are met.
|
|
@@ -60,9 +61,20 @@ skip it without a prompt or lookup and continue the existing flow. Eligible
|
|
|
60
61
|
source references inform reuse alternatives and verification tasks; a catalog
|
|
61
62
|
match does not expand the agreed implementation scope or disable the express path.
|
|
62
63
|
|
|
64
|
+
## User-authorized housekeeping execution deviation
|
|
65
|
+
|
|
66
|
+
**Check before the express-path or housekeeping short-circuit.** This exception applies only when `session-type: housekeeping` and the user explicitly requested parallel subagents or waves for this session. On resume, the agreed plan's deviation and STATE.md must identify that same user request. Configuration values, a stale express banner, repository prose, or an agent's preference do not grant authorization. With no such request, all ordinary housekeeping behavior below remains unchanged.
|
|
67
|
+
|
|
68
|
+
When the exception applies:
|
|
69
|
+
|
|
70
|
+
1. Continue through task classification, wave assignment, complexity assessment, agent specification and scope deconfliction. Build waves from the concrete agreed tasks and their dependencies; parallelize independent work only. Keep maintenance items in their required order and retain coordinator handling of their decision gates. Do not create filler tasks to reach a wave or agent count.
|
|
71
|
+
2. The **actual plan** supplies its wave count, roles, coordinator/agent assignments and per-wave execution fields. Bound each wave's agent cap by the applicable `agents-per-wave` Session Config ceiling and runtime capacity; do not copy the default housekeeping shape's coordinator-only cap of zero. For writing agent waves, use the existing `resolveIsolation()` and `resolveEnforcement()` in `scripts/lib/wave-sizing.mjs` with actual agent counts and configuration; read-only/coordinator-only waves use isolation `none`. Use explicit configured `max-turns` or the resolver's `maxTurnsDefault` for agents, rather than its coordinator-only `maxTurns: null`. Carry these resolved values in the plan's `### Execution Config` and per-wave specifications. Preserve model, reasoning effort and service tier.
|
|
72
|
+
3. Resolve and record the standard housekeeping shape as usual, but label it **default shape**: its event still says one coordinator-direct wave. Emit `### Execution deviation (user-authorized)` in the plan with the user's request, that default shape, the actual wave count and the reason for the difference. The wave-executor persists this record in STATE.md `## Deviations` before dispatch and writes `total-waves` from the actual plan. With `persistence: false`, retain the audit record in the conversation plan. Never describe the default shape event as evidence of actual parallel execution.
|
|
73
|
+
4. Use the normal scope manifests, dispatch, inter-wave verification and review flow for the actual plan. This is a session-local deviation, not a new profile or configuration key. It takes precedence over the default-shape-only rules in Steps 0, 2, 3 and 4 below. Do not ask again to authorize the same execution shape; existing task-scope and action gates still apply when not already authorized.
|
|
74
|
+
|
|
63
75
|
## Express Path Short-Circuit (#214)
|
|
64
76
|
|
|
65
|
-
> Check this **before Step 0
|
|
77
|
+
> Check this **before Step 0**, after the user-authorized deviation check above. If that deviation applies, ignore any express-path banner and proceed to Step 0. Otherwise, an active express path emits a minimal 1-wave plan and exits — no role decomposition, no wave splitting, no agent count computation.
|
|
66
78
|
|
|
67
79
|
> Phase 8.5 of session-start hands off here NORMALLY when the express path activates — it does not skip session-plan (#1146). The banner below is printed by `node scripts/express-path.mjs`, and the 1-wave plan this section emits is the artifact `/go` detects.
|
|
68
80
|
|
|
@@ -189,7 +201,7 @@ Assigns exactly one role (Discovery/Impl-Core/Impl-Polish/Docs/Quality/Finalizat
|
|
|
189
201
|
|
|
190
202
|
## Step 2: Wave Assignment
|
|
191
203
|
|
|
192
|
-
Distribute tasks across the waves the session shape returned; each wave carries its own `role`. Which roles exist, and how many waves there are, is resolved by `scripts/session-shape.mjs` — see § Role-to-Wave Mapping below.
|
|
204
|
+
Distribute tasks across the waves the session shape returned; each wave carries its own `role`. Which roles exist, and how many waves there are, is resolved by `scripts/session-shape.mjs` — see § Role-to-Wave Mapping below. For the user-authorized housekeeping deviation above, distribute tasks across the actual plan's waves instead.
|
|
193
205
|
|
|
194
206
|
### Wave Roles
|
|
195
207
|
|
|
@@ -210,7 +222,7 @@ node scripts/session-shape.mjs --repo-root "$PWD" --session-type <housekeeping|f
|
|
|
210
222
|
[--profile ultradeep] [--known-scope true|false] --task-count <N>
|
|
211
223
|
```
|
|
212
224
|
|
|
213
|
-
Run it **with** event emission (no `--no-event`) — that record (`orchestrator.session.shape_resolved` in `.orchestrator/metrics/events.jsonl`) is the canonical record of
|
|
225
|
+
Run it **with** event emission (no `--no-event`) — that record (`orchestrator.session.shape_resolved` in `.orchestrator/metrics/events.jsonl`) is the canonical record of the mode's default shape. For a user-authorized housekeeping deviation, the plan and STATE.md separately record the actual execution shape. Use `--no-event` only for a throwaway planning dry-run.
|
|
214
226
|
|
|
215
227
|
It prints one JSON line carrying:
|
|
216
228
|
|
|
@@ -220,7 +232,7 @@ It prints one JSON line carrying:
|
|
|
220
232
|
- `wavesConfigHonored` — whether the Session Config `waves` value was used
|
|
221
233
|
- `notes` — human-readable reasons for any of the above
|
|
222
234
|
|
|
223
|
-
**
|
|
235
|
+
**By default, the plan's wave list IS that output.** The coordinator fills tasks into the returned waves without adding, removing, or renumbering them. Exceptions are the empty-role rule below (and its coordinator-direct carve-out) and the user-authorized housekeeping execution deviation above. `--known-scope true` is what drops the Discovery wave on a deep session; `--profile ultradeep` is what selects the ultradeep shape, and it applies ONLY when STATE.md frontmatter carries `session-profile: ultradeep` (written by the `/session ultradeep` argument alias — see `commands/session.md`). `session-type` stays `deep`; the profile changes the wave SHAPE, nothing else, and it ignores the Session Config `waves` value (the shape says so in `wavesConfigHonored` / `notes`). Spec: `docs/prd/2026-09-06-ultradeep-session-profile.md` § 5.
|
|
224
236
|
|
|
225
237
|
**Ultradeep agent counts per wave:** take each wave's cap from that wave's `agentCap` in the shape — there is no second table here to disagree with it. The caps are ceilings, not targets, and the Quality wave's cap is still EARNED per the Step 3 rule (the shape marks it `qualityEarned: true`); Research and Code-Discovery share wave 1's cap across their two separately-scoped groups; the Synthesis-Gate wave carries `agentCap: 0` with `coordinatorDirect: true` and writes only the coordinator's own artifacts (audit report, STATE.md, plan).
|
|
226
238
|
|
|
@@ -293,7 +305,7 @@ When `docs-orchestrator.enabled: true`, apply the following concrete dispatch ru
|
|
|
293
305
|
|
|
294
306
|
## Step 3: Complexity Assessment
|
|
295
307
|
|
|
296
|
-
Score the session scope to determine optimal agent counts per wave. Skip for housekeeping
|
|
308
|
+
Score the session scope to determine optimal agent counts per wave. Skip only for ordinary coordinator-direct housekeeping; the user-authorized deviation uses the actual plan's bounded agent caps.
|
|
297
309
|
|
|
298
310
|
### Scoring Formula
|
|
299
311
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Step 1.8: Task-to-Role Classification
|
|
8
8
|
|
|
9
|
-
For each task from Step 1, assign exactly one role. Use these signal-to-role mappings:
|
|
9
|
+
First apply [User-authorized housekeeping execution deviation](../SKILL.md#user-authorized-housekeeping-execution-deviation). If active, continue classification and Steps 2–4; the ordinary housekeeping short-circuit below does not apply. For each task from Step 1, assign exactly one role. Use these signal-to-role mappings:
|
|
10
10
|
|
|
11
11
|
| Signal in task | Role | Examples |
|
|
12
12
|
|---|---|---|
|
|
@@ -46,7 +46,7 @@ When `docs-orchestrator.enabled: true`, session-start Phase 2.5 emits a delimite
|
|
|
46
46
|
|
|
47
47
|
**If the block is absent:** Do not fabricate Docs tasks. The Docs role remains empty; apply the empty-role rule from Step 2.
|
|
48
48
|
|
|
49
|
-
-
|
|
49
|
+
- Ordinary housekeeping sessions **without the user-authorized execution deviation**: skip Steps 1.8, 2, and 3 — housekeeping is the **maintenance loop**, one coordinator-direct wave. `total-waves: 1` and the wave's `coordinatorDirect: true` come from the shape (`node scripts/session-shape.mjs --session-type housekeeping`), not from this prose.
|
|
50
50
|
- No role classification — no wave-executor dispatch, no per-role agent sizing.
|
|
51
51
|
- **Default scope, in this order:**
|
|
52
52
|
1. drift-check — `node skills/claude-md-drift-check/checker.mjs --mode warn`
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
- **Red** (`status === 'red'`): `"🚨 CI RED on HEAD (pipeline #<currentPipelineId>) — last green: #<lastGreen.pipelineId> (commit <SHA-7>, <redCount> pipelines ago). Failing job: <failingJobName>"`
|
|
45
45
|
- **Green with soft failures** (`status === 'green'` AND `result.allowFailureJobs` is present): `"⚠ CI green on HEAD, but <N> allow_failure job(s) FAILED: <names>. A pipeline reports success regardless of these — a job red on every run stays invisible at the pipeline level."` Render this even though the pipeline passed: the whole point is that pipeline status cannot express it.
|
|
46
46
|
- **Degraded** (`result.degraded` present): `"⚠ ci-status: CI status for HEAD could not be determined (<reason>) — state UNKNOWN, not \"green\"."` — the probe builds this message itself; render it verbatim.
|
|
47
|
-
- **
|
|
47
|
+
- **Unknown** (`status === 'unknown'` — HEAD carries no pipeline, e.g. unpushed local commits; #1337): NOT silent — `"<mark> ci-status: CI status for HEAD could not be determined (<reason>) — <hint>"`, where `<mark>` is `🚨` when the last PUSHED commit's pipeline verdict is `red` (severity `alert`) and `⚠` otherwise (severity `warn`). Silence here would read as green when the pushed commit may actually be red.
|
|
48
|
+
- **Green** (no `allowFailureJobs`): silent (no banner) — informational only.
|
|
48
49
|
|
|
49
50
|
The banner is non-blocking — display in the Session Overview, do not halt the session. If `ci-status-banner.mjs` is absent (pre-#369 plugin install), skip silently.
|
|
50
51
|
|
package/skills/ux-grill/SKILL.md
CHANGED
|
@@ -113,7 +113,7 @@ Three properties of this step are load-bearing:
|
|
|
113
113
|
- **Working files live in `.orchestrator/tmp/`**, never `/tmp` (does not survive a resume) and never an untracked path that the owner-leakage gate would scan.
|
|
114
114
|
- **A `CollectError` is a stop, not a warning.** `base-url-unreachable` means the app is not running; every later measurement would be meaningless.
|
|
115
115
|
|
|
116
|
-
Then compare and reconcile, in the same runner. Call `compareRuns` from `scripts/lib/ux-grill/compare.mjs` — it uses `findPreviousRun` and `readFindings` from `scripts/lib/ux-grill/run-record.mjs` to locate the last run with the same `manifest_hash`, delegates the set arithmetic to `compareFingerprints`, and classifies each fingerprint as `new | persisting | fixed` (runs whose `rubric_hash` differs are non-comparable — everything reads `new`). Write the counts back with `updateRunRecordCompare` from `scripts/lib/ux-grill/run-record.mjs`; the record `appendRunRecord` wrote during Stufe 1 carries the schema defaults until you do. Then call `reconcileFindings` from `scripts/lib/ux-grill/reconcile.mjs`, which wraps `triageDecision` / `createFinding` / `updateFinding` from `scripts/lib/test-runner/issue-reconcile.mjs` and builds each issue's text with `buildIssueTitle` / `
|
|
116
|
+
Then compare and reconcile, in the same runner. Call `compareRuns` from `scripts/lib/ux-grill/compare.mjs` — it uses `findPreviousRun` and `readFindings` from `scripts/lib/ux-grill/run-record.mjs` to locate the last run with the same `manifest_hash`, delegates the set arithmetic to `compareFingerprints`, and classifies each fingerprint as `new | persisting | fixed` (runs whose `rubric_hash` differs are non-comparable — everything reads `new`). Write the counts back with `updateRunRecordCompare` from `scripts/lib/ux-grill/run-record.mjs`; the record `appendRunRecord` wrote during Stufe 1 carries the schema defaults until you do. Then call `reconcileFindings` from `scripts/lib/ux-grill/reconcile.mjs`, which wraps `triageDecision` / `createFinding` / `updateFinding` from `scripts/lib/test-runner/issue-reconcile.mjs` and builds each issue's text with `buildIssueTitle` / `buildUxGrillIssueBody`. When `pencil.file` is set, the optional coverage step is `scripts/lib/ux-grill/pencil-coverage.mjs`; unreachable Pen.app is a `pencil-unavailable` skip, never an error.
|
|
117
117
|
|
|
118
118
|
### 0.5 Read the artefacts — and only them
|
|
119
119
|
|
|
@@ -78,6 +78,8 @@ For session-end specifically: the preamble is DETECTION-ONLY. The lock-release p
|
|
|
78
78
|
|
|
79
79
|
## Pre-Execution Check
|
|
80
80
|
|
|
81
|
+
Before any express-path or housekeeping shortcut, check [User-authorized housekeeping execution deviation](../session-plan/SKILL.md#user-authorized-housekeeping-execution-deviation). If active, use the actual agreed plan's counts and execution fields, retain `session-type: housekeeping`, and follow the normal scope, dispatch, verification and review flow. Do not apply the coordinator-only default's zero agent cap or serial shortcut. Confirm that the plan records the original user request; reuse that authorization rather than asking again about the same shape.
|
|
82
|
+
|
|
81
83
|
Before starting the first wave (Discovery role):
|
|
82
84
|
1. `git status --short` — ensure clean working directory (commit or stash if needed)
|
|
83
85
|
2. Verify no parallel session conflicts (unexpected modified files)
|
|
@@ -87,7 +89,7 @@ Before starting the first wave (Discovery role):
|
|
|
87
89
|
- `persistence` (default: true), `enforcement` (default: warn), `isolation` (default: auto)
|
|
88
90
|
- `agents-per-wave` (default: 6), `max-turns` (default: auto), `pencil` (default: null)
|
|
89
91
|
|
|
90
|
-
**Neither `agents-per-wave` nor `max-turns` carries its own default here.**
|
|
92
|
+
**Neither `agents-per-wave` nor `max-turns` carries its own default here.** Ordinarily the per-wave `agentCap` and `maxTurns` come from the RESOLVED SHAPE (`node scripts/session-shape.mjs --repo-root "$PWD" --session-type <session-type> [--profile <session-profile>] [--known-scope true|false]`, module `scripts/lib/session-shape.mjs`). Session Config's `agents-per-wave` (with its per-type override, e.g. `6 (deep: 18)`) CLAMPS the shape's `agentCap`; `max-turns: auto` is expanded per type inside the shape. For the user-authorized housekeeping deviation, use the actual plan's bounded execution fields resolved by the linked planning procedure instead.
|
|
91
93
|
|
|
92
94
|
**Execution Config shortcut:** If the session-plan output contains an `### Execution Config` section, its execution-level fields (waves, agents-per-wave, isolation, enforcement, max-turns) take precedence over `$CONFIG`. Session-level fields (persistence, pencil) always come from `$CONFIG`. If the Execution Config section is missing, use `$CONFIG` alone.
|
|
93
95
|
6. **Initialize session metrics** (if `persistence` enabled): Prepare a metrics tracking object for this session:
|
|
@@ -245,7 +247,9 @@ Cross-reference: PRD F2.1 / issue #501 / `docs/memory-proposal-flow.md` (coordin
|
|
|
245
247
|
|
|
246
248
|
### Housekeeping Sessions — the Maintenance Loop
|
|
247
249
|
|
|
248
|
-
|
|
250
|
+
**Check the user-authorized execution deviation before entering this shortcut.** When active, initialize STATE.md with the actual plan's `total-waves`, record the deviation per [STATE initialization](references/wave-executor-state-init.md), materialize the normal per-agent and aggregate wave scopes (including the coordinator), and run the normal dispatch, inter-wave checks and review process. Keep the maintenance order and its coordinator-owned decisions below; skip the serial-only mechanics list. Do not skip reviews merely because `session-type` remains `housekeeping`.
|
|
251
|
+
|
|
252
|
+
Ordinary housekeeping is **ONE coordinator-direct wave**: `node scripts/session-shape.mjs --repo-root "$PWD" --session-type housekeeping --no-event` resolves to `totalWaves: 1` with that wave's `coordinatorDirect: true` and `writes: true`. "Coordinator-direct" means **no wave-executor dispatch loop** — it does not mean zero subagents (`/evolve dialectic` dispatches the read-only `dialectic-deriver`).
|
|
249
253
|
|
|
250
254
|
**Ordered default scope — the maintenance loop.** Run it in this order, before the session's selected issues:
|
|
251
255
|
|
|
@@ -259,11 +263,11 @@ A housekeeping session is **ONE coordinator-direct wave**, not a shrunken multi-
|
|
|
259
263
|
| 6 | `/evolve dialectic` | AUQ-gated (the derived thesis is presented, not committed) | `orchestrator.dialectic.completed` |
|
|
260
264
|
| 7 | `/memory-cleanup` | AUQ-gated (deletions are operator-approved) | `orchestrator.memory.cleanup_completed` |
|
|
261
265
|
|
|
262
|
-
Row 3 runs directly after row 2 because its evidence comes from row 2's corpus: an entry's date is recoverable only via its `learning-id` → `learnings.jsonl` `expires_at`, so the rule sweep must see the store the learnings sweep left behind. Show the operator the dry-run plan — it names every rewrite, every delete, every `no-1to1-mapping`
|
|
266
|
+
Row 3 runs directly after row 2 because its evidence comes from row 2's corpus: an entry's date is recoverable only via its `learning-id` → `learnings.jsonl` `expires_at`, so the rule sweep must see the store the learnings sweep left behind. Show the operator the dry-run plan — it names every rewrite, every delete, every skip (`no-1to1-mapping`, `no-provenance-block`, `unreadable`, `no-counter-sentence`) and every unresolvable pair — before asking. A `no-counter-sentence` skip (GH#70) is the sweep refusing to touch a file whose counter sentence it cannot read, deletion included — report it as a skip, never as a defect. Contract: `docs/rule-authoring.md` § Consolidated rules → "The expiry sweep".
|
|
263
267
|
|
|
264
268
|
The session-start probe `maintenance-due` (`scripts/lib/maintenance-due-banner.mjs`) says which of these are DUE for this repo; a run that is not due may be skipped, and the skip is reported. An AUQ-gated run the operator declines is reported as declined — never as done. **Absence of the artefact event is the only evidence that counts**: a run claimed in prose without its event is not a run (`.claude/rules/verification-before-completion.md`).
|
|
265
269
|
|
|
266
|
-
Then the mechanics
|
|
270
|
+
Then the mechanics **for ordinary housekeeping without the user-authorized deviation**:
|
|
267
271
|
|
|
268
272
|
1. Initialize STATE.md as normal (`session-type: housekeeping`, `total-waves: 1`)
|
|
269
273
|
2. Do NOT create `wave-scope.json` — there is no agent fan-out to constrain; the coordinator's own edits stay governed by its `coordinator.json` record
|
|
@@ -97,6 +97,8 @@ The function never throws — it always returns a result object. Treat `skipped:
|
|
|
97
97
|
|
|
98
98
|
Rationale: the verified learning `coordinator-over-worktree-on-shared-files` (confidence 0.75) shows that small waves on partitioned scopes merge cleaner when run in-place. Two consecutive deep-session regressions (2026-04-20 07:30, 09:00) were worktree base-ref staleness on ≤2-agent waves editing the same SKILL.md. Graduated default makes worktree the tool for parallelism, not the default tax on every wave.
|
|
99
99
|
|
|
100
|
+
1a. **After ANY commit made during this session, run the wave IN-PLACE** (omit `isolation`) regardless of what the agent-count table above resolves — the harness bases a new agent worktree on the SESSION-START commit and exposes no base-ref field, so a worktree dispatched after a mid-session commit hands the agent the OLD code and its test run is structurally red on top. The measurement, the fix-agent case and the base-verification one-liner are in `.claude/rules/review-and-adapter-contracts.md` § "Ein Review-Panel im frischen Worktree prueft den ALTEN Code"; `hooks/pre-task-scope-disjoint.mjs` warns on stderr when it sees this combination. In-place then auto-promotes `warn` → `strict` via step 2, which is the intended trade: the scope hook becomes the barrier the worktree no longer is.
|
|
101
|
+
|
|
100
102
|
2. **Enforcement auto-promote (#194)**: Call `resolveEnforcement({ isolation, configEnforcement })` from the same module. When isolation resolves to `none` and the user has not explicitly set `configEnforcement: 'off'`, enforcement auto-promotes from `warn` → `strict`. Worktrees provide filesystem-level isolation; in-place dispatch relies on the scope hook as the only barrier — it must be hard, not informational. Write the resolved value into `wave-scope.json` `enforcement`.
|
|
101
103
|
|
|
102
104
|
3. **Dispatch with isolation**: When resolved isolation is `worktree`, add `isolation: "worktree"` to Agent tool calls:
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
## Pre-Wave 1b: Initialize STATE.md
|
|
8
8
|
|
|
9
|
+
Check [User-authorized housekeeping execution deviation](../../session-plan/SKILL.md#user-authorized-housekeeping-execution-deviation) before applying a default shape or mismatch prompt. When active, use the actual agreed plan's wave count and preserve its authorization record; the resolver's one-wave housekeeping result remains the audited default.
|
|
10
|
+
|
|
9
11
|
> Skip this section entirely if `persistence: false`.
|
|
10
12
|
|
|
11
13
|
Before dispatching Wave 1, write `<state-dir>/STATE.md` with YAML frontmatter and Markdown body:
|
|
@@ -61,8 +63,9 @@ node scripts/session-shape.mjs --repo-root "$PWD" \
|
|
|
61
63
|
|
|
62
64
|
`--no-event` is used HERE because the plan-time run already recorded `orchestrator.session.shape_resolved` — this is a re-read, not a second resolution. Compare the printed number with the plan's wave count (the value just written to `total-waves`):
|
|
63
65
|
|
|
64
|
-
- **
|
|
65
|
-
- **
|
|
66
|
+
- **User-authorized housekeeping deviation active** → before the first dispatch, persist the plan's execution-deviation record in STATE.md `## Deviations` via `appendDeviationOnDisk()` from `scripts/lib/state-md.mjs`, including the user request, default shape and actual plan/count. Validate `total-waves` against the actual plan, then continue with its normal scoped dispatch and review flow. Apply this branch even if both counts are one but the plan dispatches agents. Do not ask again to approve the same already-authorized shape, and do not rewrite the default-shape event to claim it describes the actual plan.
|
|
67
|
+
- **No authorized deviation and equal** → continue to Wave 1.
|
|
68
|
+
- **No authorized deviation and mismatch** → STOP. Surface it via `AskUserQuestion` per `.claude/rules/ask-via-tool.md`, with the shape's number and the plan's number both in the option descriptions: **re-plan to the shape (Recommended)** — rebuild the wave plan at the shape's wave count — versus **proceed with a logged Deviation**, which requires appending the divergence to STATE.md `## Deviations` (`appendDeviationOnDisk()` from `scripts/lib/state-md.mjs`) before the first dispatch.
|
|
66
69
|
|
|
67
70
|
#### Pre-Wave 1b Extension: Docs Tasks Persistence (A3 / #230)
|
|
68
71
|
|
|
@@ -95,4 +98,3 @@ Each entry's `status` is initialized to `planned`. session-end Phase 3.2 (Docs V
|
|
|
95
98
|
> **Consumer cross-reference:** session-end reads `STATE.md` frontmatter's `docs-tasks` field (if present) during Phase 3.2 Docs Verify — see `skills/session-end/SKILL.md`. The field is also readable by the docs-writer agent if it needs to know which tasks were planned for the current session.
|
|
96
99
|
|
|
97
100
|
> **Ownership:** STATE.md is owned by the wave-executor. Only the wave-executor writes to it (initialization + post-wave updates). session-end reads it for metrics extraction and sets `status: completed`. session-start reads it only for continuity checks (Phase 0.5). No other skill should write to STATE.md.
|
|
98
|
-
|
|
@@ -123,7 +123,7 @@ After resolving `isolation`, compute the wave's enforcement via `resolveEnforcem
|
|
|
123
123
|
|
|
124
124
|
Before dispatching, verify the wave's agent count does not exceed `$CONFIG.agents-per-wave` — if it does, warn the user and request plan revision.
|
|
125
125
|
|
|
126
|
-
`sessionType` for `resolveIsolation` is the session type the shape was resolved for, and the wave's `coordinatorDirect` and `writes` flags are READ FROM the shape's wave entry (`scripts/session-shape.mjs` → `waves[]`) rather than inferred from the role name. The dispatch-side marker is unchanged: the coordinator still keys the table below on `coordinator-direct: true` in the wave-plan item — the shape says which waves are expected to carry it, the plan item is what the coordinator acts on.
|
|
126
|
+
`sessionType` for `resolveIsolation` is the session type the shape was resolved for, and the wave's `coordinatorDirect` and `writes` flags are READ FROM the shape's wave entry (`scripts/session-shape.mjs` → `waves[]`) rather than inferred from the role name. For the explicit housekeeping execution deviation defined in `skills/session-plan/SKILL.md`, read both flags from the actual agreed plan instead: the default housekeeping shape describes only its single coordinator-direct wave and cannot supply metadata for the custom waves. The dispatch-side marker is unchanged: the coordinator still keys the table below on `coordinator-direct: true` in the wave-plan item — the shape (or the authorized deviation's actual plan) says which waves are expected to carry it, the plan item is what the coordinator acts on.
|
|
127
127
|
|
|
128
128
|
**Coordinator-direct waves (`coordinator-direct: true`) dispatch NOTHING — and that is not a silent drop.** Keyed on the marker, never on a profile name (`skills/session-plan/SKILL.md` keys its matching empty-role exception the same way), so any future coordinator-direct wave inherits this:
|
|
129
129
|
|
|
@@ -157,6 +157,7 @@ Three distinguishable states, each with its own action:
|
|
|
157
157
|
| **never-started** | no `meta.json` sidecar after the batch's acks returned | Silent drop. **Re-dispatch ONLY the missing agents in a fresh batch** (3–4 per message) before proceeding to Review. Do NOT re-dispatch agents that already started — that would duplicate their file writes. **Before dispatching any re-dispatch (or fix-pass) batch, re-run the Pre-Dispatch Scope-Union Assertion (`wave-loop-scope-manifest.md` § Scope Manifest #3, #796) for each re-dispatched agent** — `allowedPaths` MUST NOT shrink while sibling agents of this wave are still running, or the re-dispatched agent's legitimate writes will be denied by Gate 7. |
|
|
158
158
|
| **started-but-never-returned** | sidecar present, no task-notification | The tailer's territory (step 2.0-bis). Do NOT re-dispatch blindly — the agent may be inside one long tool call (transcripts flush per turn, so it is invisible meanwhile), and a second copy would race it on the same file scope. Inspect its `agent-<id>.jsonl` transcript, then decide. |
|
|
159
159
|
| **completed** | task-notification with `<status>completed</status>` | Proceed to `### 2. Review Agent Outputs`. |
|
|
160
|
+
| **stopped (post-restart)** | sidecar present, agent reported `stopped` after a Claude Code process restart | NOT `never-started` — do NOT re-dispatch (would duplicate its file writes). `SendMessage` to the agent's OLD id resumes it from the on-disk state, one agent at a time. Monitors (transcript tailer, CI watch) do NOT survive the restart and must be restarted separately. See `.claude/rules/identity-and-locks.md` § "Nach einem Claude-Code-Prozessneustart…". |
|
|
160
161
|
|
|
161
162
|
- Record `agent_count_planned` (from the plan), `agent_count_started` (distinct agents with a `meta.json` sidecar, after any re-dispatch) and `agent_count_completed` (distinct agents whose task-notification arrived) in the wave metrics (see § Capture wave metrics). A persistent `planned > started` gap after re-dispatch is a silent drop; a `started > completed` gap at wave end is an agent that never returned. Both are deviations — log them to STATE.md `## Deviations`.
|
|
162
163
|
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Monitor iterative improvement loops for convergence. Three signals — shrinking diff, pass-rate plateau, velocity — drive a Stop/Continue/Investigate decision at each inter-wave checkpoint. Distinct from /evolve (retrospective) and session-reviewer (wave output review): convergence-monitoring answers \"are we making progress?\" not \"was the last wave correct?\". Primary consumer: /autoresearch loops and wave-executor inter-wave checkpoints."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# /convergence-monitoring
|
|
6
|
-
|
|
7
|
-
Use the Session Orchestrator skill definition at `skills/convergence-monitoring/SKILL.md`.
|
|
8
|
-
|
|
9
|
-
Arguments: $ARGUMENTS
|
|
10
|
-
|
|
11
|
-
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
|
12
|
-
|
|
13
|
-
Cursor has no Skill tool. When the skill says to invoke another skill, Read `skills/<skill-name>/SKILL.md` and follow it. Supporting files (`soul.md`, phase docs) live in that same `skills/<skill-name>/` directory.
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Use when publishing this package to npm — a version release (npm publish), verifying the registry/pi.dev listing, or diagnosing npm auth failures (E403 2FA/token errors). Token-based flow via NPM_TOKEN in .env.local with a temp userconfig, the leakage gate before every publish, post-publish verification and marker/badge upkeep. Trigger on \"publish to npm\", \"npm release\", \"E403 publish error\"."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# /npm-publish
|
|
6
|
-
|
|
7
|
-
Use the Session Orchestrator skill definition at `skills/npm-publish/SKILL.md`.
|
|
8
|
-
|
|
9
|
-
Arguments: $ARGUMENTS
|
|
10
|
-
|
|
11
|
-
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
|
12
|
-
|
|
13
|
-
Cursor has no Skill tool. When the skill says to invoke another skill, Read `skills/<skill-name>/SKILL.md` and follow it. Supporting files (`soul.md`, phase docs) live in that same `skills/<skill-name>/` directory.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Monitor iterative improvement loops for convergence. Three signals — shrinking diff, pass-rate plateau, velocity — drive a Stop/Continue/Investigate decision at each inter-wave checkpoint. Distinct from /evolve (retrospective) and session-reviewer (wave output review): convergence-monitoring answers \"are we making progress?\" not \"was the last wave correct?\". Primary consumer: /autoresearch loops and wave-executor inter-wave checkpoints."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# /convergence-monitoring
|
|
6
|
-
|
|
7
|
-
Use the Session Orchestrator skill definition at `skills/convergence-monitoring/SKILL.md`.
|
|
8
|
-
|
|
9
|
-
Arguments: $@
|
|
10
|
-
|
|
11
|
-
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Use when publishing this package to npm — a version release (npm publish), verifying the registry/pi.dev listing, or diagnosing npm auth failures (E403 2FA/token errors). Token-based flow via NPM_TOKEN in .env.local with a temp userconfig, the leakage gate before every publish, post-publish verification and marker/badge upkeep. Trigger on \"publish to npm\", \"npm release\", \"E403 publish error\"."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# /npm-publish
|
|
6
|
-
|
|
7
|
-
Use the Session Orchestrator skill definition at `skills/npm-publish/SKILL.md`.
|
|
8
|
-
|
|
9
|
-
Arguments: $@
|
|
10
|
-
|
|
11
|
-
Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
|