AGENTS.md · git:20261021.728a583 · 2026-10-21 · sha256 e3147123061c1780
AGENTS.md git:20261021.728a583A
Immutable. This exact content never changes and is served at /api/v1/blob/e3147123061c1780.
# Session Orchestrator Plugin
> 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).
> Lean root by design (Anthropic large-codebase best-practice: root = pointers + critical gotchas). Delegated docs:
> - **Install, CLI usage, architecture, component inventory** → [`README.md`](./README.md) (full inventory: [`docs/components.md`](./docs/components.md))
> - **Plugin ↔ private baseline relationship** (what degrades without it, the public fallback) → [`docs/baseline.md`](./docs/baseline.md)
> - **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)
> - **Stable product/tech/structure context** → [`.orchestrator/steering/`](./.orchestrator/steering/) (injected at session-start Phase 2.6)
> - **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)
> - **Decisions log** (hand-authored) → [[01-projects/session-orchestrator/decisions]] in the Meta-Vault
> - **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`
> - **Operator tmux side-channel** → `/tmux-layout` (4-pane: STATE.md/CI-watch/events; [ADR-0007](docs/adr/0007-tmux-visualization-substrate.md))
>
> **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.
## Current State <!-- consistency:exempt:lean-root-pointer-section -->
State-free by design (see the **Live state is not in this file** gotcha below) — SSOTs:
- **Version + test/coverage** → README badges
- **Per-session metrics & history** → [`.orchestrator/metrics/sessions.jsonl`](./.orchestrator/metrics/sessions.jsonl)
- **Decisions** (hand-authored) → [[01-projects/session-orchestrator/decisions]] (Meta-Vault) · **Session narrative** (generated) → `_session-narrative.md` beside it
## Critical Gotchas <!-- consistency:exempt:lean-root-pointer-section -->
These are the non-obvious, mistake-causing facts that must load every session. Everything else is delegated above.
- **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 -->
- **Destructive-Command Guard** (`hooks/pre-bash-destructive-guard.mjs`, `.orchestrator/policy/blocked-commands.json`: 12 block + 4 warn rules) runs on Claude Code, Cursor/Pi and Codex (deny honoured, codex-cli 0.160.1, 2026-10-20, #1691). PSA-003 (`parallel-sessions.md`); bypass `allow-destructive-ops: true`; #1401: `docs/session-config-reference.md`. <!-- consistency:exempt:runtime-only -->
- **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.
- **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.
- **`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 -->
- **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.
`/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 -->
- **`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`.
`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 -->
- **`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 -->
## Session Config
persistence: true
enforcement: warn
agents-per-wave: 6 (deep: 18)
waves: 5
recent-commits: 20
test-command: npm test
typecheck-command: npm run typecheck
lint-command: npm run lint
stale-branch-days: 7
plugin-freshness-days: 30
plan-baseline-path: OVERRIDE-IN-owner.yaml # placeholder, NOT a real path — resolve host-locally
plan-prd-location: docs/prd
plan-retro-location: docs/retro
plan-default-visibility: internal
vcs: gitlab
mirror: curated
auto-skill-dispatch: false
vault-integration:
enabled: true
vault-dir: ~/Projects/vault
mode: warn
vault-name:
docs-orchestrator:
enabled: false
audiences: [user, dev, vault]
mode: warn
vault-staleness:
enabled: false
thresholds:
top: 30
active: 60
archived: 180
mode: warn
docs-staleness:
enabled: false
thresholds:
living: 90
mode: warn
moc-staleness:
enabled: false
thresholds:
moc: 90
mode: warn
context-coverage:
enabled: false
mode: warn
worktree-orphans:
enabled: false
base-branch: main
mode: warn
drift-check:
enabled: true
mode: warn
check-docs-parity: true
wave-reviewers:
enabled: false
reviewers: []
mode: warn
memory-cleanup-soft-limit: 180
vault-mirror:
quality:
min-narrative-chars: 400
min-confidence: 0.5
memory:
banner:
enabled: true
proposals:
enabled: true
quota-per-wave: 5
confidence-floor: 0.5
auto-dream:
min-confidence: 0.5
cold-start:
enabled: true
nudge-after-hours: 1
silence-after-sessions: 1
state-md-lock:
enabled: true
timeout-ms: 10000
handover-gate:
enabled: true
max-open-questions: 3
issue-budget:
max-per-session: 12
mode: strict
overflow: collect-issue
broken-window-budget:
enabled: false
due-days: 7
slopcheck:
enabled: false
sources: [plan, discovery]
templates-first:
enabled: true
hosts: [github, gitlab]
verification-auto-fix:
enabled: false
max-retries: 2
discovery-validator:
enabled: false
frontend-slop-hook:
enabled: false
loop-guard:
enabled: true
threshold: 3
window: 5
instruction-budget:
enabled: true
ceiling: 480
mode: warn
config-protection:
enabled: true
mode: warn
allow-config-weakening: false
custom-phases:
- name: archive-closed-prds
when: both
command: node scripts/archive-closed-prds.mjs --apply
mode: warn
- name: archive-closed-plans
when: both
command: node scripts/archive-closed-prds.mjs --apply --prd-dir docs/plans --vault-subdir 01-projects/session-orchestrator/plans
mode: warn
remote-hosts:
- alias: m5
roles-allowed: [test, ui, perf]
- alias: m5-remote
roles-allowed: [test, ui, perf]
evolve:
extra-sources: []
dialectic:
cadence: 5
model: haiku
budget-tokens: 32000
eval:
enabled: true
mode: warn
judge: off
report: html
handle:
reconcile:
enabled: false
mode: warn
targets: [repo-local]
rule-expiry-days: null
confidence-floor: 0.5
min-rule-days: 7
min-insight-chars: 24
## Skill Evolution <!-- consistency:exempt:parity-exempt-skill-evolution-block -->
> 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.
> 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.
skill-evolution:
autonomy: autonomous-gated # off | advisory | autonomous-gated — armed (#652)
evidence-floor: 0.5 # float 0.0..1.0 — min evidence before an autonomous-gated repair acts
judge: off # opt-in session-end LLM-judge (advisory only); default off
## Dispatcher Autonomy <!-- consistency:exempt:parity-exempt-dispatcher-autonomy-block -->
> **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.
> 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`.
> See `docs/session-config-reference.md` § Dispatcher Autonomy for the #681 capture history and the full precedence chain.
dispatcher-autonomy:
autonomy: off # off | advisory | autonomous-gated — default off (fail-closed)
confidence-floor: 0.5 # float 0.0..1.0