session-orchestrator 4.1.0 → 5.0.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/session-plan/SKILL.md +1 -1
- package/.agents/skills/session-start/SKILL.md +1 -1
- package/.agents/skills/ux-grill/SKILL.md +22 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.codex-plugin/skills/session-plan/SKILL.md +1 -1
- package/.codex-plugin/skills/session-start/SKILL.md +1 -1
- package/.codex-plugin/skills/ux-grill/SKILL.md +21 -0
- package/.codex-plugin/skills/ux-grill/agents/openai.yaml +5 -0
- package/.cursor/commands/ux-grill.md +14 -0
- package/.cursor/skills/session-plan/SKILL.md +1 -1
- package/.cursor/skills/session-start/SKILL.md +1 -1
- package/.cursor/skills/ux-grill/SKILL.md +13 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +128 -1
- package/README.md +98 -86
- package/agents/dialectic-deriver.md +11 -0
- package/agents/ux-evaluator.md +1 -1
- package/commands/close.md +3 -3
- package/commands/go.md +2 -0
- package/commands/memory-cleanup.md +4 -3
- package/commands/persona-panel.md +1 -1
- package/commands/session.md +3 -2
- package/commands/ux-grill.md +51 -0
- package/docs/README.md +4 -4
- package/docs/USER-GUIDE.md +117 -50
- package/docs/agent-authoring.md +2 -2
- package/docs/baseline.md +55 -1
- package/docs/ci-setup.md +1 -1
- package/docs/codex-setup.md +9 -0
- package/docs/components.md +9 -9
- package/docs/cursor-setup.md +1 -0
- package/docs/events-schema.md +13 -6
- package/docs/github-mirror-protection.md +61 -20
- package/docs/instruction-delivery.md +1 -1
- package/docs/memory-proposal-flow.md +3 -3
- package/docs/migration-v4.md +2 -2
- package/docs/migration-v5.md +62 -0
- package/docs/owner-config-schema.md +74 -90
- package/docs/persona-panel.md +4 -4
- package/docs/pi-setup.md +1 -0
- package/docs/rule-authoring.md +13 -6
- package/docs/scope-collision-guard.md +16 -0
- package/docs/session-config-reference.md +55 -22
- package/docs/session-config-template.md +9 -5
- package/docs/vault-docs-architecture.md +4 -2
- package/hooks/_lib/hook-import-set.json +70 -3
- package/hooks/_lib/lock-bootstrap.mjs +84 -1
- package/hooks/_lib/vcs-create-matcher.mjs +401 -16
- package/hooks/enforce-scope.mjs +201 -0
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +5 -0
- package/hooks/hooks.json +7 -2
- package/hooks/on-session-start.mjs +171 -49
- package/hooks/post-bash-issue-budget-refund.mjs +375 -0
- package/hooks/pre-auq-clarity.mjs +70 -18
- package/hooks/pre-bash-issue-budget.mjs +170 -26
- package/hooks/subagent-telemetry.mjs +106 -20
- package/package.json +5 -4
- package/pi/prompts/ux-grill.md +12 -0
- package/scripts/baseline-archetypes.mjs +28 -0
- package/scripts/ci/assert-vitest-green.mjs +4 -2
- package/scripts/dialectic-deriver.mjs +32 -8
- package/scripts/emit-session.mjs +72 -1
- package/scripts/lib/agent-status.mjs +441 -9
- package/scripts/lib/auq/schema.mjs +10 -3
- package/scripts/lib/auto-dialectic.mjs +0 -68
- package/scripts/lib/baseline-archetypes.mjs +439 -0
- package/scripts/lib/build-live-signals.mjs +5 -6
- package/scripts/lib/ci-status-banner.mjs +29 -6
- package/scripts/lib/claude-md-budget-lint.mjs +52 -2
- package/scripts/lib/config/issue-budget.mjs +68 -8
- package/scripts/lib/config/private-config-dir.mjs +3 -2
- package/scripts/lib/config/remote-hosts.mjs +2 -2
- package/scripts/lib/config-schema.mjs +79 -0
- package/scripts/lib/config.mjs +12 -1
- package/scripts/lib/eval/engine.mjs +7 -1
- package/scripts/lib/file-lock.mjs +151 -8
- package/scripts/lib/git-porcelain.mjs +113 -0
- package/scripts/lib/instruction-budget-guard.mjs +415 -47
- package/scripts/lib/io.mjs +29 -4
- package/scripts/lib/issue-budget-reconcile.mjs +392 -0
- package/scripts/lib/issue-budget.mjs +412 -9
- package/scripts/lib/learnings/evolve-telemetry.mjs +1 -2
- package/scripts/lib/learnings/sizing-subject.mjs +44 -0
- package/scripts/lib/locks/staging-fence-lock.mjs +19 -38
- package/scripts/lib/locks/state-md-lock.mjs +19 -41
- package/scripts/lib/maintenance-due-banner.mjs +450 -0
- package/scripts/lib/owner-config.example.yaml +29 -46
- package/scripts/lib/owner-yaml.mjs +14 -13
- package/scripts/lib/peer-cards/merger.mjs +143 -0
- package/scripts/lib/pre-dispatch-check.mjs +20 -14
- package/scripts/lib/project-hygiene.mjs +81 -30
- package/scripts/lib/quality-gate.mjs +27 -71
- package/scripts/lib/reconcile/engine.mjs +19 -1
- package/scripts/lib/reconcile/writer.mjs +278 -11
- package/scripts/lib/resource-probe/evaluate.mjs +19 -21
- package/scripts/lib/rules-sync.mjs +34 -4
- package/scripts/lib/scope-echo.mjs +346 -0
- package/scripts/lib/session-close-backfill.mjs +182 -40
- package/scripts/lib/session-end/phase-skip.mjs +85 -86
- package/scripts/lib/session-end/tail-runner.mjs +178 -0
- package/scripts/lib/session-lock.mjs +62 -2
- package/scripts/lib/session-record-repair.mjs +91 -0
- package/scripts/lib/session-schema/constants.mjs +6 -0
- package/scripts/lib/session-schema/filters.mjs +26 -1
- package/scripts/lib/session-schema/validator.mjs +20 -0
- package/scripts/lib/session-shape.mjs +558 -0
- package/scripts/lib/session-start-probes.mjs +429 -56
- package/scripts/lib/session-token-rollup.mjs +95 -10
- package/scripts/lib/state-md/frontmatter-mutators.mjs +22 -34
- package/scripts/lib/state-md.mjs +1 -0
- package/scripts/lib/subagents-schema.mjs +77 -9
- package/scripts/lib/telemetry/pricing.mjs +197 -0
- package/scripts/lib/telemetry/sync.mjs +50 -1
- package/scripts/lib/test-runner/artifact-paths.mjs +30 -5
- package/scripts/lib/test-runner/issue-reconcile.mjs +45 -8
- package/scripts/lib/tmux-layout/layouts.mjs +62 -4
- package/scripts/lib/ux-grill/collect.mjs +1163 -0
- package/scripts/lib/ux-grill/compare.mjs +285 -0
- package/scripts/lib/ux-grill/manifest.mjs +618 -0
- package/scripts/lib/ux-grill/measures.mjs +431 -0
- package/scripts/lib/ux-grill/paths.mjs +224 -0
- package/scripts/lib/ux-grill/pencil-coverage.mjs +284 -0
- package/scripts/lib/ux-grill/reconcile.mjs +344 -0
- package/scripts/lib/ux-grill/run-record.mjs +316 -0
- package/scripts/lib/ux-grill/schema.mjs +321 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +33 -10
- package/scripts/lib/validate/check-untracked-test-deps.mjs +33 -19
- package/scripts/lib/validate/check-unwired-features.mjs +56 -27
- package/scripts/lib/vault-mirror/process.mjs +2 -1
- package/scripts/lib/vault-status/board-lock.mjs +18 -0
- package/scripts/lib/vault-status/board-writer.mjs +8 -0
- package/scripts/lib/vault-status/narrative-mirror.mjs +4 -4
- package/scripts/lib/wave-resource-gate.mjs +23 -27
- package/scripts/lib/wave-sizing.mjs +10 -3
- package/scripts/materialize-wave-scope.mjs +68 -14
- package/scripts/mcp-server.sh +16 -1
- package/scripts/print-applicable-rules.mjs +7 -6
- package/scripts/print-learnings-index.mjs +3 -2
- package/scripts/release.mjs +7 -2
- package/scripts/session-shape.mjs +266 -0
- package/skills/_shared/config-reading.md +15 -9
- package/skills/_shared/private-capability-context.md +89 -0
- package/skills/bootstrap/SKILL.md +60 -209
- package/skills/bootstrap/_shared-template.md +99 -14
- package/skills/bootstrap/deep-template.md +36 -26
- package/skills/bootstrap/fast-template.md +44 -8
- package/skills/bootstrap/intensity-heuristic.md +10 -4
- package/skills/bootstrap/private-contract.md +119 -0
- package/skills/bootstrap/public-fallback.md +30 -18
- package/skills/bootstrap/references/bootstrap-ecosystem-health-flow.md +48 -0
- package/skills/bootstrap/references/bootstrap-refresh-lock-flow.md +37 -0
- package/skills/bootstrap/references/bootstrap-retroactive-flow.md +108 -0
- package/skills/bootstrap/references/bootstrap-rules-fetch-bridge.md +64 -0
- package/skills/bootstrap/standard-template.md +39 -24
- package/skills/claude-md-drift-check/SKILL.md +9 -2
- package/skills/claude-md-drift-check/checker.mjs +213 -21
- package/skills/discovery/SKILL.md +6 -173
- package/skills/discovery/probes/vault-staleness.mjs +35 -5
- package/skills/discovery/probes-docs.md +8 -4
- package/skills/discovery/probes-supply-chain.md +4 -2
- package/skills/discovery/probes-ui.md +8 -4
- package/skills/discovery/probes-vault.md +12 -4
- package/skills/discovery/references/discovery-interactive-triage.md +139 -0
- package/skills/discovery/references/discovery-triage-state.md +54 -0
- package/skills/docs-orchestrator/audience-mapping.md +1 -1
- package/skills/eval/rubric-v1.md +13 -0
- package/skills/evolve/SKILL.md +2 -458
- package/skills/evolve/references/evolve-analyze-mode.md +360 -0
- package/skills/evolve/references/evolve-dialectic-mode.md +139 -0
- package/skills/gitlab-ops/SKILL.md +3 -3
- package/skills/grill/SKILL.md +1 -1
- package/skills/memory-cleanup/SKILL.md +2 -2
- package/skills/plan/mode-new.md +9 -0
- package/skills/plan/mode-retro.md +4 -3
- package/skills/reconcile/SKILL.md +11 -1
- package/skills/session-end/SKILL.md +3 -2
- package/skills/session-end/drift-operations.md +20 -5
- package/skills/session-end/metrics-collection.md +1 -0
- package/skills/session-end/phase-3-2-docs-verification.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +27 -67
- package/skills/session-end/phase-3-7a-recommendations.md +2 -2
- package/skills/session-end/references/phase-2-quality-gate.md +3 -3
- package/skills/session-end/references/phase-3-documentation-updates.md +8 -6
- package/skills/session-end/references/phase-5-issue-cleanup.md +32 -1
- package/skills/session-end/session-metrics-write.md +33 -12
- package/skills/session-plan/SKILL.md +46 -180
- package/skills/session-plan/references/session-plan-task-classification.md +152 -0
- package/skills/session-plan/wave-template.md +8 -15
- package/skills/session-start/SKILL.md +41 -7
- package/skills/session-start/phase-2-5-docs-planning.md +1 -1
- package/skills/session-start/phase-8-5-express-path.md +12 -9
- package/skills/session-start/references/operations-contract.md +114 -0
- package/skills/session-start/references/phase-1-5-session-continuity.md +2 -0
- package/skills/session-start/references/phase-4-ssot-environment-check.md +42 -24
- package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +3 -1
- package/skills/session-start/soul.md +2 -2
- package/skills/test-runner/SKILL.md +1 -1
- package/skills/test-runner/rubric-v1.md +2 -2
- package/skills/tmux-layout/SKILL.md +3 -1
- package/skills/ux-grill/SKILL.md +211 -0
- package/skills/ux-grill/rubric-v2.md +201 -0
- package/skills/ux-grill/soul.md +76 -0
- package/skills/wave-executor/SKILL.md +32 -127
- package/skills/wave-executor/circuit-breaker.md +3 -1
- package/skills/wave-executor/references/wave-executor-quality-gate.md +61 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +86 -0
- package/skills/wave-executor/references/wave-loop-dispatch.md +12 -2
- package/skills/wave-executor/references/wave-loop-review.md +19 -6
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +6 -2
- package/templates/_shared/ux-manifest.template.md +149 -0
- package/templates/nextjs-minimal/package.json +1 -1
- package/templates/node-minimal/package.json +1 -1
- package/scripts/lib/multi-provider-build/providers.mjs +0 -64
- package/scripts/lib/multi-provider-build/templating.mjs +0 -130
- package/scripts/lib/owner-config/coerce.mjs +0 -29
- package/scripts/lib/owner-config/constants.mjs +0 -21
- package/scripts/lib/owner-config/defaults.mjs +0 -50
- package/scripts/lib/owner-config/error.mjs +0 -19
- package/scripts/lib/owner-config/index.mjs +0 -13
- package/scripts/lib/owner-config/merge.mjs +0 -52
- package/scripts/lib/owner-config/validate.mjs +0 -259
- package/scripts/lib/owner-config-loader.mjs +0 -170
- package/scripts/lib/owner-config.mjs +0 -28
- package/scripts/lib/soul-resolve.mjs +0 -130
- package/scripts/lib/vault-mirror/render.mjs +0 -8
- package/templates/_shared/journey-manifest.md +0 -114
|
@@ -5,13 +5,19 @@
|
|
|
5
5
|
>
|
|
6
6
|
> Issue [#174](../../../-/issues/174) — D1 of Sub-Epic [#161](../../../-/issues/161) (Owner Persona Layer).
|
|
7
7
|
> Parent epic: [#157](../../../-/issues/157) (v3.1.0 Environment-Aware Sessions).
|
|
8
|
+
>
|
|
9
|
+
> **SSOT is code, not this file:** `scripts/lib/owner-yaml.mjs` (schema,
|
|
10
|
+
> validator, loader, writer) + `scripts/lib/config/private-config-dir.mjs`
|
|
11
|
+
> (path resolution). This page describes that module; when the two disagree,
|
|
12
|
+
> the module wins.
|
|
8
13
|
|
|
9
14
|
## Path Resolution
|
|
10
15
|
|
|
11
|
-
The loader (`scripts/lib/owner-
|
|
16
|
+
The loader (`scripts/lib/owner-yaml.mjs`, via `resolvePrivateConfigDir()` in
|
|
17
|
+
`scripts/lib/config/private-config-dir.mjs`) resolves the canonical path as:
|
|
12
18
|
|
|
13
19
|
```
|
|
14
|
-
${XDG_CONFIG_HOME ?? <homedir>/.config}/session-orchestrator/owner.yaml
|
|
20
|
+
${SO_CONFIG_HOME ?? XDG_CONFIG_HOME ?? <homedir>/.config}/session-orchestrator/owner.yaml
|
|
15
21
|
```
|
|
16
22
|
|
|
17
23
|
| Platform | Default path |
|
|
@@ -21,37 +27,40 @@ ${XDG_CONFIG_HOME ?? <homedir>/.config}/session-orchestrator/owner.yaml
|
|
|
21
27
|
| Windows | `%USERPROFILE%\.config\session-orchestrator\owner.yaml` |
|
|
22
28
|
|
|
23
29
|
A missing file is **not an error** — it signals the user has not opted in.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
30
|
+
`loadOwnerConfig()` then returns `getDefaults()` with `source: 'defaults'`.
|
|
31
|
+
|
|
32
|
+
## Schema
|
|
33
|
+
|
|
34
|
+
Four **required** sections (`owner`, `tone`, `efficiency`, `hardware-sharing`)
|
|
35
|
+
and the optional sections below. An invalid required section discards the whole
|
|
36
|
+
file (defaults are returned, errors reported); an invalid optional object
|
|
37
|
+
section is replaced by its default and reported via `droppedSections`
|
|
38
|
+
(`source: 'partial'`).
|
|
39
|
+
|
|
40
|
+
| Section / Field | Type / enum | Required | Default | Notes |
|
|
41
|
+
|-------------------------------------|--------------------------------------|----------|-----------|----------------------------------------------------|
|
|
42
|
+
| `owner.name` | non-empty string | yes | `''` | Display name. |
|
|
43
|
+
| `owner.language` | `de` \| `en` | yes | `en` | Drives soul.md default language. |
|
|
44
|
+
| `tone.style` | `direct` \| `neutral` \| `friendly` | yes | `neutral` | |
|
|
45
|
+
| `tone.tonality` | string or absent | no | `''` | Free-form descriptor. |
|
|
46
|
+
| `efficiency.output-level` | `lite` \| `full` \| `ultra` | yes | `full` | Token dial. |
|
|
47
|
+
| `efficiency.preamble` | `minimal` \| `verbose` | yes | `minimal` | Pre-tool-call narration. |
|
|
48
|
+
| `hardware-sharing.enabled` | boolean | yes | `false` | Consent gate for hardware-pattern export. |
|
|
49
|
+
| `hardware-sharing.hash-salt` | string | no | `''` | Required (non-empty) when `enabled = true`. |
|
|
50
|
+
| `paths.vault-dir` | string | no | `''` | `''` = no override; beats the committed `vault-integration.vault-dir`. |
|
|
51
|
+
| `paths.baseline-path` | string | no | `''` | Host-local `plan-baseline-path` override (#653). |
|
|
52
|
+
| `paths.namespace-map-path` | string | no | `''` | Host-local repo-pseudonym JSON map (#725 D5). |
|
|
53
|
+
| `paths.confidential-names-file` | string | no | `''` | Host-local JSON array of names for the CP11 leakage rule (#728a). Names live in that file only, never inline here. |
|
|
54
|
+
| `dispatcher.autonomy` | `off` \| `advisory` \| `autonomous-gated` \| `''` | no | `''` | `''` = no override (#679). |
|
|
55
|
+
| `vaults`, `baselines` | lists | no | absent | Passed through untouched; parsed leniently at point of use. |
|
|
46
56
|
|
|
47
57
|
### Privacy Contract
|
|
48
58
|
|
|
49
|
-
- `hardware-sharing.enabled = true` **requires**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
it is hashed (never plaintext email) and remains optional.
|
|
59
|
+
- `hardware-sharing.enabled = true` **requires** a non-empty
|
|
60
|
+
`hardware-sharing.hash-salt`. The validator rejects consent without the means
|
|
61
|
+
to anonymise per-host learnings.
|
|
62
|
+
- Only PATHS live in `owner.yaml`; the host-local data they point at
|
|
63
|
+
(confidential names, namespace map) is never inlined and never committed.
|
|
55
64
|
|
|
56
65
|
## Example
|
|
57
66
|
|
|
@@ -60,95 +69,70 @@ for an annotated, copyable example.
|
|
|
60
69
|
|
|
61
70
|
## API Surface
|
|
62
71
|
|
|
63
|
-
`scripts/lib/owner-
|
|
72
|
+
`scripts/lib/owner-yaml.mjs` — the live SSOT. **Synchronous**; every call site
|
|
73
|
+
consumes it without `await`. `js-yaml` is imported lazily, so the module is
|
|
74
|
+
safe on the hook import graph.
|
|
64
75
|
|
|
65
76
|
```js
|
|
66
|
-
import {
|
|
67
|
-
|
|
68
|
-
// Defensive, never throws. Use this in skill code paths.
|
|
69
|
-
const result = validate(rawObj);
|
|
70
|
-
// → { ok: true, value: <normalized>, errors: [] }
|
|
71
|
-
// → { ok: false, value: null, errors: ["owner.name must be ..."] }
|
|
72
|
-
|
|
73
|
-
// Strict mode: throws OwnerConfigError on failure. Use in tests / CLI.
|
|
74
|
-
const value = coerce(rawObj);
|
|
75
|
-
|
|
76
|
-
// Default-filled config. owner.name and owner.language remain blank
|
|
77
|
-
// (the bootstrap interview in D2 fills them in).
|
|
78
|
-
const def = defaults();
|
|
77
|
+
import { loadOwnerConfig, resolveOwnerYamlPath, validateOwnerConfig, getDefaults }
|
|
78
|
+
from './scripts/lib/owner-yaml.mjs';
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
const merged = merge(baseFromOwnerYaml, perSessionOverrides);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
`scripts/lib/owner-config-loader.mjs` (filesystem I/O):
|
|
85
|
-
|
|
86
|
-
```js
|
|
87
|
-
import { loadOwnerConfig, resolveOwnerConfigPath } from './scripts/lib/owner-config-loader.mjs';
|
|
88
|
-
|
|
89
|
-
const result = await loadOwnerConfig();
|
|
80
|
+
const result = loadOwnerConfig();
|
|
90
81
|
// {
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
// errors: string[],
|
|
94
|
-
// source: 'file' | 'missing' | 'parse-error' | 'validation-error',
|
|
82
|
+
// config: <merged with getDefaults()>,
|
|
83
|
+
// source: 'file' | 'partial' | 'defaults' | ...,
|
|
95
84
|
// path: '<absolute path>',
|
|
85
|
+
// errors: string[], warnings: string[], droppedSections: string[],
|
|
96
86
|
// }
|
|
97
87
|
|
|
98
88
|
// Test override
|
|
99
|
-
const result2 =
|
|
89
|
+
const result2 = loadOwnerConfig({ path: '/tmp/test-owner.yaml' });
|
|
90
|
+
|
|
91
|
+
// Pure validation, no I/O, never throws.
|
|
92
|
+
const { valid, errors } = validateOwnerConfig(rawObj);
|
|
100
93
|
```
|
|
101
94
|
|
|
95
|
+
Also exported: `validateOwnerSections()` (per-section buckets),
|
|
96
|
+
`writeOwnerConfig()`, `OPTIONAL_OBJECT_SECTIONS`, `resolvePrivateConfigDir`.
|
|
97
|
+
|
|
102
98
|
## Where this gets read
|
|
103
99
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
`{{efficiency.output-level}}` / `{{owner.language}}` template slots.
|
|
114
|
-
- **#177 D4 — projects-baseline propagation**: stamps a
|
|
115
|
-
reference to the canonical path into every consumer repo's CLAUDE.md
|
|
116
|
-
frontmatter (path reference only — never the content).
|
|
117
|
-
- **[#168 C4](../../../-/issues/168) — hardware-sharing consent prompt**: writes
|
|
118
|
-
`hardware-sharing.enabled = true` + a freshly-generated `hash-salt` after
|
|
119
|
-
the user accepts the consent dialogue.
|
|
100
|
+
`loadOwnerConfig()` has 10 live consumers outside its own module
|
|
101
|
+
(`rg -ln "loadOwnerConfig" scripts hooks`, 2026-09-09) — two hooks
|
|
102
|
+
(`hooks/on-session-start.mjs`, `hooks/skill-invocation-telemetry.mjs`), the
|
|
103
|
+
session-start owner-config banner (`scripts/lib/owner-config-banner.mjs`), the
|
|
104
|
+
host-path + dispatcher-autonomy resolvers (`scripts/lib/config/host-paths.mjs`,
|
|
105
|
+
`scripts/lib/config/dispatcher-autonomy.mjs`), the named-vault resolver, the
|
|
106
|
+
owner-leakage scanner, telemetry, and vault-mirror. For the behavioural
|
|
107
|
+
contract of the persona layer itself see
|
|
108
|
+
[`.claude/rules/owner-persona.md`](../.claude/rules/owner-persona.md).
|
|
120
109
|
|
|
121
110
|
## Validation Rules (rejection examples)
|
|
122
111
|
|
|
123
112
|
```yaml
|
|
124
|
-
# REJECTED —
|
|
125
|
-
owner: { name: x, language: en }
|
|
126
|
-
|
|
127
|
-
# REJECTED — schema-version mismatch (refuses to load future versions)
|
|
128
|
-
schema-version: 2
|
|
129
|
-
owner: { name: x, language: en }
|
|
130
|
-
|
|
131
|
-
# REJECTED — name empty
|
|
132
|
-
schema-version: 1
|
|
113
|
+
# REJECTED — owner.name empty
|
|
133
114
|
owner: { name: "", language: en }
|
|
134
115
|
|
|
135
|
-
# REJECTED — language
|
|
136
|
-
schema-version: 1
|
|
116
|
+
# REJECTED — language outside the de|en enum
|
|
137
117
|
owner: { name: x, language: "english" }
|
|
138
118
|
|
|
139
119
|
# REJECTED — enum violation
|
|
140
|
-
schema-version: 1
|
|
141
120
|
owner: { name: x, language: en }
|
|
142
121
|
tone: { style: "snarky" }
|
|
143
122
|
|
|
144
123
|
# REJECTED — privacy contract: enabled=true without hash-salt
|
|
145
|
-
schema-version: 1
|
|
146
124
|
owner: { name: x, language: en }
|
|
147
125
|
hardware-sharing: { enabled: true }
|
|
148
126
|
|
|
149
|
-
# ACCEPTED —
|
|
150
|
-
schema-version: 1
|
|
127
|
+
# ACCEPTED — all four required sections present and valid
|
|
151
128
|
owner:
|
|
152
129
|
name: Bernhard
|
|
153
130
|
language: de
|
|
131
|
+
tone:
|
|
132
|
+
style: direct
|
|
133
|
+
efficiency:
|
|
134
|
+
output-level: full
|
|
135
|
+
preamble: minimal
|
|
136
|
+
hardware-sharing:
|
|
137
|
+
enabled: false
|
|
154
138
|
```
|
package/docs/persona-panel.md
CHANGED
|
@@ -70,8 +70,8 @@ written to `.orchestrator/persona-panel/`.
|
|
|
70
70
|
**Scenario:** A climate-research brief (`wfk-2.1.5.md`) needs sign-off from a domain physicist
|
|
71
71
|
and an AI/ML expert before it is submitted. Both must agree.
|
|
72
72
|
|
|
73
|
-
**Catalog files:** `.claude/personas/klima-physicist.md`,
|
|
74
|
-
`.claude/personas/klima-ai-expert.md`
|
|
73
|
+
**Catalog files:** `.claude/personas/klima-physicist.md`, <!-- path-check: example -->
|
|
74
|
+
`.claude/personas/klima-ai-expert.md` <!-- path-check: example -->
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
/persona-panel docs/research/wfk-2.1.5.md \
|
|
@@ -182,8 +182,8 @@ The command exits with code 1. CI pipelines and wave-executor hooks can gate on
|
|
|
182
182
|
**Scenario:** An AI accountant (Sophie) produces invoice analysis JSON. A tax-advisor persona
|
|
183
183
|
and a DSGVO-compliance persona must both approve before the output is delivered to the client.
|
|
184
184
|
|
|
185
|
-
**Catalog files:** `.claude/personas/accounting-tax-advisor.md`,
|
|
186
|
-
`.claude/personas/accounting-compliance.md`
|
|
185
|
+
**Catalog files:** `.claude/personas/accounting-tax-advisor.md`, <!-- path-check: example -->
|
|
186
|
+
`.claude/personas/accounting-compliance.md` <!-- path-check: example -->
|
|
187
187
|
|
|
188
188
|
```bash
|
|
189
189
|
/persona-panel sophie-outputs/2026-05-19/invoice-12345.json \
|
package/docs/pi-setup.md
CHANGED
|
@@ -118,5 +118,6 @@ After reload, use the same commands:
|
|
|
118
118
|
- **Prompts or skills not visible**: verify the project is trusted in Pi, then restart or reload.
|
|
119
119
|
- **Package not loaded**: confirm `.pi/settings.json` or `~/.pi/agent/settings.json` contains the local checkout path under `packages`.
|
|
120
120
|
- **Hooks not firing**: confirm `package.json` still has the `pi.extensions` entry and `hooks/hooks-pi.json` exists.
|
|
121
|
+
- **No import-probe warning after an edit**: Pi wires the probe through `tool_result`; file eligibility, ESLint resolution, and `no-undef` configuration still apply. See [import-probe coverage and ESLint troubleshooting](USER-GUIDE.md#import-probe-warnings-and-missing-eslint).
|
|
121
122
|
- **Config ignored**: ensure the file has a `## Session Config` header in `AGENTS.md` or `CLAUDE.md`.
|
|
122
123
|
- **Runtime error from hooks**: run `npm install` in the Session Orchestrator checkout so hook dependencies are present.
|
package/docs/rule-authoring.md
CHANGED
|
@@ -285,12 +285,19 @@ them silently loses a learning or regenerates it:
|
|
|
285
285
|
TTL past what its type registry granted it.) State the rule in the file
|
|
286
286
|
itself, so the next editor does not "fix" it upward.
|
|
287
287
|
|
|
288
|
-
3. **Keep `globs:`
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
3. **Keep BOTH `globs:` and `paths:`, as byte-identical mirrors, each the
|
|
289
|
+
UNION of the parts.** The merged file loads for any path any of its parts
|
|
290
|
+
covered, so both lists are the union of theirs — never `globs:` alone.
|
|
291
|
+
`rule-loader.mjs` resolves `globs:` for wave-time injection, while Claude
|
|
292
|
+
Code's OWN native rule loader reads ONLY `paths:` and treats a rule
|
|
293
|
+
lacking it as unconditional, always-on (`check-rules.mjs` check #1108,
|
|
294
|
+
measured this session) — a `globs:`-only merged file is scoped everywhere
|
|
295
|
+
it is inspected and loads everywhere it is used, exactly the
|
|
296
|
+
instruction-budget failure consolidation exists to prevent. `rule-loader.mjs`
|
|
297
|
+
still resolves `globs:` and `paths:` with `globs:` winning SILENTLY when
|
|
298
|
+
both are present (issue #795, `parseGlobsFrontmatter`), but keeping the two
|
|
299
|
+
lists identical makes that precedence moot — there is no divergent value
|
|
300
|
+
left for it to pick between.
|
|
294
301
|
|
|
295
302
|
4. **Substance in, boilerplate out.** Each absorbed learning becomes an `###`
|
|
296
303
|
heading carrying its original rule sentence, plus its evidence line. What is
|
|
@@ -25,6 +25,8 @@ Two things follow, and both are the point of #1020:
|
|
|
25
25
|
|
|
26
26
|
`<state-dir>` is the first of `.pi` / `.cursor` / `.codex` / `.claude` that carries a `wave-scope.json` — the same precedence `findScopeFile()` and the hook's `waveKeyOf()` use.
|
|
27
27
|
|
|
28
|
+
Step 1 also offers an opt-in path diagnostic: run `materialize-wave-scope.mjs` from the project root with `--warn-missing` to name absent concrete paths and their agents on stderr (#1235). Relative paths resolve from the working directory, not `<state-dir>`. A warning does not fail the command or change its stdout or either declaration shape. For a file the wave deliberately creates, repeat `--new-file PATH` as needed; every exception must exactly match a declared path and pass scope validation before any writes begin. Grants containing `*` or ending in `/` are skipped under the existing glob/prefix grammar; `?` and braces are literal. The canonical invocation and handling steps are in `skills/wave-executor/references/wave-loop-scope-manifest.md` § 3.1.
|
|
29
|
+
|
|
28
30
|
### 2.1 Why `--union` runs last
|
|
29
31
|
|
|
30
32
|
A union computed over colliding scopes **launders the defect into the artefact meant to prevent it**: `allowedPaths` then grants the contested file, and every later gate — `--assert-subset`, `enforce-scope` Gate 7, the commit guard — sees a perfectly legal write. `validate()` in `validate-wave-scope.mjs` enforces the order in code: `--assert-subset` → `--assert-disjoint` → `--union`, and `--union` returns early because it is a QUERY MODE that replaces the manifest echo on stdout.
|
|
@@ -62,6 +64,14 @@ Five properties are choices, not omissions — and every one of them points the
|
|
|
62
64
|
|
|
63
65
|
The event is what keeps the skip countable rather than silent: `orchestrator.scope.foreign_session_ignored` carries `hook`, `manifest`, `manifest_session`, `own_session`, `wave` and `file_path`. It is deliberately an event and not an `emitWarn` — the branch is hit on *every* Edit of the non-owning session, so a stderr line per write would be noise the operator learns to ignore.
|
|
64
66
|
|
|
67
|
+
### 2.4 The one out-of-repo territory: harness auto-memory (#1295)
|
|
68
|
+
|
|
69
|
+
`hooks/enforce-scope.mjs` Gate 5c allows writes under **this repo's** Claude Code auto-memory directory, `~/.claude/projects/<encoded-repo-path>/memory/` (`<encoded-repo-path>` = the repo root with every `/` and `.` replaced by `-`, via the one repo encoder `encodeProjectDir()` in `scripts/lib/wave-transcript-tail.mjs`). The harness writes `MEMORY.md` and the per-fact files there, outside the working copy, so those paths can never collide with any wave file scope — yet Gate 6 denied every one of them while a manifest existed, and six sessions in a consumer repo re-documented the same tear-down-the-manifest workaround (bewerbungs-assistent#307). One `orchestrator.scope.memory_dir_allowed` event per allow makes it countable.
|
|
70
|
+
|
|
71
|
+
The grant is exactly one directory: containment is exact-prefix on the realpath-resolved candidate (both the raw and the canonical project root are encoded, since Claude Code names the directory after the path it was launched with), so a SIBLING repo's memory dir, an adjacent-prefix sibling directory (`<memory>-evil/`), a `..` traversal out of it, and every other out-of-repo path stay denied. One honest caveat: the harness name is not unique — `encodeProjectDir()` maps both `/` and `.` to `-`, so two repo roots differing only in `.` vs `-` (`/x/a.b` and `/x/a-b`) share ONE memory dir. That collision is the harness's, inherited here and not narrowable by this gate — and in-repo enforcement, including Discovery's `allowedPaths: []` deny-all, is untouched. The encoder is bound lazily and a load failure falls through to the deny (fail-closed). **Who the grant is for (#1352): the COORDINATOR only.** The carve-out opens a directory whose content is auto-injected as trusted project context into every later session, outside `git diff`, CI review, owner-leakage and gitleaks — so a dispatched wave agent must not reach it. The discriminator is the payload's **`agent_id`**, and it is measured, not assumed (Claude Code 2.1.270, `strings` over the shipped binary, 2026-09-13): the base hook-input builder every event shares is `{session_id, transcript_path: yf(session.id), cwd, …, agent_id: toolUseContext?.agentId, agent_type}`, which PreToolUse spreads verbatim, and the harness's own schema says of `agent_id` — *"Present only when the hook fires from within a subagent… Absent for the main thread, even in `--agent` sessions. Use this field (not `agent_type`) to distinguish subagent calls from main-thread calls."* The issue's original candidate is refuted by the same source: `transcript_path` is derived from the SESSION id, so coordinator and subagent carry the identical value; so is `CLAUDE_CODE_SESSION_ID`, and `CLAUDE_CODE_CHILD_SESSION=1` was measured in a main-thread `env` dump (`isSidechain:false`).
|
|
72
|
+
|
|
73
|
+
`classifyCaller()` therefore returns `subagent` (non-empty `agent_id` → **no carve-out**; the write falls through to the normal gates, which is a DENY under Discovery's `allowedPaths: []`), `coordinator` (no `agent_id` but a non-empty `agent_type` — per the schema that combination is the main thread of an `--agent` session), or `absent` (neither field). **`absent` keeps the pre-#1352 ALLOW, deliberately fail-OPEN:** fail-closed on ambiguity would deny the coordinator's own memory writes and break `/close`, and a harness that sends no marker is indistinguishable from a main thread. The outcome rides on the existing `orchestrator.scope.memory_dir_allowed` event as `discriminator`, so the fail-open case is countable rather than silent (HR-105) — revisit if `absent` ever dominates the records on a harness that does dispatch subagents.
|
|
74
|
+
|
|
65
75
|
## 3. The collision algorithm
|
|
66
76
|
|
|
67
77
|
`findScopeCollisions(agentScopes, { knownFiles })` compares every cross-agent entry pair through `classifyEntryCollision()`, in three binding stages:
|
|
@@ -141,6 +151,12 @@ Why it exists: the in-ledger `scopeSignals` counter (§ 4.1, rows 5/6) is a **wa
|
|
|
141
151
|
|
|
142
152
|
**Payload discipline.** Counts and closed enums only, plus `agent_id` (the coordinator's own dispatch description, clamped) and the optional session attribution: no prompt body, no declared path, no glob. Issue #1092's acceptance criterion 3 is the rule, and the reason is concrete — this record also travels over the optional Clank Event-Bus webhook with no redaction, and paths under `01-projects/` carry private project slugs.
|
|
143
153
|
|
|
154
|
+
**The receive side now has a SOFT self-report signal (#1092).** Beside the fenced `FILE-SCOPE` block the coordinator injects one line naming the `scopeDigest` of that agent's own scope file (`scripts/lib/scope-echo.mjs --instruction`); post-wave, `checkScopeEcho` compares the digest the agent echoed in its report and emits one `orchestrator.wave_dispatch.scope_echo_checked` record per agent (`skills/wave-executor/references/wave-loop-review.md` step 3d-bis). It is informational — a missing or mismatched echo blocks nothing.
|
|
155
|
+
|
|
156
|
+
**Its ceiling, named (BV-004).** The digest is *handed to the agent in the prompt*, so an agent that never read a single path can still copy the line. The signal therefore proves only that the injected line survived the round trip into the agent's context and back — strictly more than the zero receive-side signal that preceded it, and strictly less than obedience, which stays measured at write time (`enforce-scope.mjs`) and by the W5 pass. Revisit when the platform exposes a prompt-assembly boundary, at which point the digest can be computed against the assembled prompt rather than echoed by its reader.
|
|
157
|
+
|
|
158
|
+
A cryptographic proof still needs that platform boundary: no mechanism inside this repo can distinguish a copied digest from a read one.
|
|
159
|
+
|
|
144
160
|
**Revisit-Trigger** (verbatim from issue #1092, for the transport half this section deliberately does NOT close):
|
|
145
161
|
|
|
146
162
|
> Implement when the platform exposes a stable prompt-assembly hook or when a coordinator-owned digest event can be proven against the real dispatched transcript.
|
|
@@ -76,12 +76,33 @@ Some sub-configs live in dedicated policy files under `.orchestrator/policy/`:
|
|
|
76
76
|
|
|
77
77
|
| Field | Type | Default | Description |
|
|
78
78
|
|-------|------|---------|-------------|
|
|
79
|
-
| `agents-per-wave` | integer or integer with overrides | `6` | Maximum parallel subagents per wave. Supports session-type overrides: `6 (deep: 18)` outputs `{"default": 6, "deep": 18}`. The override key set is OPEN — `_coerceInteger` (`scripts/lib/config/coercers.mjs`) parses whatever keys the parentheses contain, so `6 (deep: 18, ultradeep: 18)` outputs `{"default": 6, "deep": 18, "ultradeep": 18}` with no code change (see § Session Profile below). Plain integers remain plain. The override key names a session type but does **not** create one: there is no `session-type:` Session Config key — `parseSessionConfig()` emits none, so writing one into a repo's `## Session Config` block is inert prose. The session type comes from the `/session` argument (default `deep`, see `commands/session.md`) and is persisted to STATE.md frontmatter as `session-type:`, which is the only live read (`scripts/print-applicable-rules.mjs` rule mode-gating). |
|
|
79
|
+
| `agents-per-wave` | integer or integer with overrides | `6` | Maximum parallel subagents per wave. Supports session-type overrides: `6 (deep: 18)` outputs `{"default": 6, "deep": 18}`. The override key set is OPEN — `_coerceInteger` (`scripts/lib/config/coercers.mjs`) parses whatever keys the parentheses contain, so `6 (deep: 18, ultradeep: 18)` outputs `{"default": 6, "deep": 18, "ultradeep": 18}` with no code change (see § Session Profile below). Plain integers remain plain. The override key names a session type but does **not** create one: there is no `session-type:` Session Config key — `parseSessionConfig()` emits none, so writing one into a repo's `## Session Config` block is inert prose. The session type comes from the `/session` argument (default `deep`, see `commands/session.md`) and is persisted to STATE.md frontmatter as `session-type:`, which is the only live read (`scripts/print-applicable-rules.mjs` rule mode-gating). **Resolution for wave shaping** is `resolveAgentCap(cap, sessionType)` in `scripts/lib/session-shape.mjs` — the one EXPORTED resolver. `wave-resource-gate.mjs` and `resource-probe/evaluate.mjs` both import and call this same function for their resource-ceiling checks, but each does so through a local `MODE_BLIND_SESSION_TYPE` constant (`undefined`) instead of the session's real type — two mode-blind CALL SITES, not separate resolvers — so `resolveAgentCap` sees no type and takes the `.default` fallback unconditionally; a difference between their answer and the wave-shape answer is expected, not a bug. Ultradeep looks up `ultradeep` → `deep` → `default`, in that order (`resolveUltradeepCap()`), so a repo that only configured `6 (deep: 18)` still gets 18 under the profile. See § Session Shapes below. |
|
|
80
80
|
| `agent-mapping` | object | null | Optional mapping of role keys to agent names for explicit agent binding. Keys: `impl`, `test`, `db`, `ui`, `security`, `compliance`, `docs`, `perf`. Example: `{ impl: code-editor, test: test-specialist }`. Overrides auto-discovery when present. Values may carry a channel prefix — see § `agent-mapping` values below. |
|
|
81
|
-
| `waves` | integer | `5` |
|
|
81
|
+
| `waves` | integer | `5` | Base wave count, read by `resolveSessionShape()` (`scripts/lib/session-shape.mjs`) as the value it reports back in `wavesConfigHonored` / `wavesConfigIgnoredValue` — it is **not** a free dial per session type. `feature` and `deep` (no profile) each have exactly one natural wave count and IGNORE a `waves` value that disagrees with it (recorded in the shape's `notes`, never used to re-combine roles — the former 3/4/6+ role-combination tables are RETIRED as of 2026-09-09). The `ultradeep` profile ignores `waves` outright regardless of its value (`wavesConfigHonored: false`) — PRD `2026-09-06-ultradeep-session-profile.md` AC-9 ("`waves < 7` is an error") was dropped in favour of this explicit ignore-and-report. See § Session Shapes below for the authoritative per-shape wave counts. |
|
|
82
82
|
| `recent-commits` | integer | `20` | Number of recent commits to display during session start git analysis. |
|
|
83
83
|
| `special` | string | none | Repo-specific instructions. Freeform text that the orchestrator reads and follows during sessions. |
|
|
84
84
|
|
|
85
|
+
### Session Shapes
|
|
86
|
+
|
|
87
|
+
`scripts/lib/session-shape.mjs` is the one place a `/session` mode + optional `--profile` becomes an execution shape (wave count, roles, agent caps, Discovery on/off, per-wave `max-turns`), driven via the CLI wrapper `scripts/session-shape.mjs`:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
node scripts/session-shape.mjs --repo-root <path> --session-type <housekeeping|feature|deep> \
|
|
91
|
+
[--profile ultradeep] [--known-scope true|false] [--task-count <n>] [--no-event]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
It prints one JSON line (`resolveSessionShape()`'s return value) and, unless `--no-event`, records `orchestrator.session.shape_resolved` to `.orchestrator/metrics/events.jsonl`. Four shapes, resolved 2026-09-09 (decided by the operator, superseding the prose it replaces — see the module's own header for the full rationale):
|
|
95
|
+
|
|
96
|
+
| Shape | Waves | Roles (agent cap) | Discovery | Coordinator-direct |
|
|
97
|
+
|---|---|---|---|---|
|
|
98
|
+
| `housekeeping` | **1** | Housekeeping (0 — coordinator runs the maintenance loop directly: drift-check, sweep, evolve, reconcile, dialectic, memory-cleanup) | n/a | yes, the whole wave |
|
|
99
|
+
| `feature` | **3** | Impl-Core (4) → Impl-Polish+Quality (4) → Finalization (2) | no | no |
|
|
100
|
+
| `deep` (unknown scope) | **5** | Discovery (8) → Impl-Core (10) → Impl-Polish (8) → Quality (6) → Finalization (4) | yes | no |
|
|
101
|
+
| `deep` (`--known-scope true`) | **4** | Impl-Core (10) → Impl-Polish (8) → Quality (6) → Finalization (4) | no (dropped, rest renumbered) | no |
|
|
102
|
+
| `deep` + `--profile ultradeep` | **7**, fixed — ignores `waves` | Research+Code-Discovery (18) → **Synthesis-Gate (0, coordinator-direct, blocking AskUserQuestion)** → Impl-Core (8) → Impl-Polish (8) → Review-Panel (3, read-only) → Quality (6) → Release/Finalization (4) | yes (wave 1) | wave 2 only |
|
|
103
|
+
|
|
104
|
+
Raw caps are the `agents-per-wave` value BEFORE the session-type override resolves (`agentCapRaw` in the JSON); `agentCap` is the resolved number. `max-turns` (`auto`) expands per shape — see the `max-turns` row below. This table is descriptive of the module's committed defaults; the module itself, not this table, is the SSOT — re-run the CLI with `--no-event` to confirm before citing a number from here in an automated check.
|
|
105
|
+
|
|
85
106
|
### Session Profile — `session-profile` (NOT a Session Config key)
|
|
86
107
|
|
|
87
108
|
`session-profile` names a WAVE-SHAPE variant on top of an unchanged `session-type`. It is listed here because it is easy to look for in the wrong place: **it is not a Session Config key and `parseSessionConfig()` does not emit one.** Writing `session-profile:` into a repo's `## Session Config` block is inert prose, exactly like `session-type:` (see the `agents-per-wave` row above).
|
|
@@ -270,15 +291,19 @@ issue-budget:
|
|
|
270
291
|
|
|
271
292
|
| Field | Type | Default | Description |
|
|
272
293
|
|-------|------|---------|-------------|
|
|
273
|
-
| `issue-budget.max-per-session` | integer | `12` | Non-exempt issues one session may create before the cap bites. `0` is valid (blocks everything non-exempt). Malformed or negative values fall back to `12`. |
|
|
294
|
+
| `issue-budget.max-per-session` | integer or integer with overrides | `12` | Non-exempt issues one session may create before the cap bites. `0` is valid (blocks everything non-exempt). Malformed or negative values fall back to `12`. **Accepts the same session-type override syntax `agents-per-wave` uses**: `12 (feature: 6)` parses via `_coerceInteger` into `{default: 12, feature: 6}`. The override key set is OPEN — any session-type label the operator writes, because the vocabulary lives in session-start, not in this parser. |
|
|
274
295
|
| `issue-budget.mode` | string | `strict` | `strict` blocks over-cap creations (exit 2 from the hook) and parks them as overflow; `warn` allows them with a stderr notice; `off` disables the gate entirely (no counter is written). |
|
|
275
296
|
| `issue-budget.overflow` | string | `collect-issue` | Where session-end drains parked creations. `collect-issue` files exactly ONE `[Backlog-Sammel] <session-id>, N zurückgestellte Punkte` issue (`type::backlog`, `priority::low`) whose body is a checklist of the parked items; `vault-note` writes a single Markdown file under `vault/00-inbox/` instead. |
|
|
276
297
|
|
|
298
|
+
**Override resolution (#1163-adjacent, load-bearing split).** `_parseIssueBudget()` (`scripts/lib/config/issue-budget.mjs`) returns TWO keys: `"max-per-session"` (always a plain number — the resolved `.default`, so the three existing consumers that treat it as a number never see `[object Object]`) and `"max-per-session-raw"` (the full parsed value, number or override object). `loadIssueBudgetConfig()` (`scripts/lib/issue-budget.mjs`) resolves the effective cap for the CURRENT session by reading `session-type:` off the active STATE.md frontmatter (`readSessionTypeFromStateMd()`, never throws — a missing/unparseable STATE.md yields `null`, read as "use the default") and calling `resolveMaxPerSession(cfg, sessionType)`, whose precedence is `raw[sessionType] ?? raw.default ?? cfg['max-per-session']`. The resolved session type is also returned as `"session-type-resolved"` (`null` when STATE.md carries none) so a caller can tell the resolution actually happened rather than fallen through.
|
|
299
|
+
|
|
277
300
|
**Exemptions (load-bearing).** `priority::critical`, the carryover class (`[Carryover]`, `[SPIRAL]`/`[FAILED]`, `type::carryover`, a bare `carryover` label) and `broken-window` closure issues bypass the cap unconditionally. Without those exemptions the cap would break the standing session-end promises in `skills/session-end/SKILL.md` (Phase 1.8 "non-deselectable" SPIRAL/FAILED carryover, and the Critical Rule "ALWAYS create issues for unfinished PLANNED work"). Exempt creations are counted in the state file's `exempt` field for observability but never blocked.
|
|
278
301
|
|
|
279
302
|
**Counter file:** `.orchestrator/runtime/issue-budget/<sha256(sessionId)[0..16]>.json` — `{ sessionId, count, exempt, overflow: [...] }`, ONE file per session (#1141: the former single `issue-budget.json` slot was reset by whichever session wrote last, so two sessions in one working copy silently disabled each other's cap). Identity-less callers still use the legacy flat path; `budgetStatePath(repoRoot, sessionId)` in `scripts/lib/issue-budget.mjs` is the resolver.
|
|
280
303
|
|
|
281
|
-
**
|
|
304
|
+
**Close-time reconcile (#1163).** The cap is enforced by a PreToolUse hook, which only sees the shell routes it pattern-matches — every unmatched creation route (a GUI-created issue, an unmatched CLI form) is a silent zero: no ledger line, no error, indistinguishable from "created nothing". `scripts/lib/issue-budget-reconcile.mjs` closes that gap at session-end by comparing two independently-produced numbers: `recorded` (`record.issues_created.length` from the session record) against `charged + exempt` (summed over BOTH the semantic-id and raw-id ledger keys — which key a given session's counter file used depends on a condition, `resolveIssueBudgetSessionId`, that can change mid-session). It emits `orchestrator.issue_budget.reconciled` with a `verdict`: `match` (recorded ≤ charged + exempt), `escaped` (`recorded > charged + exempt` — some creations bypassed the hook), `no-ledger` (`recorded > 0` and no counter file existed under either key — the hook never ran once), or `stale-record` (a ledger exists but the record shows 0 recorded with a positive charge). Fail-open by contract: nothing in this module throws, and a close-time cross-check that could abort the close would be strictly worse than one that reports `no-ledger`.
|
|
305
|
+
|
|
306
|
+
**Used by:** `hooks/pre-bash-issue-budget.mjs` (shell path, PreToolUse/Bash, now charges **per statement** rather than per whole command — see `hooks/_lib/vcs-create-matcher.mjs`, which also matches `gh|glab api … POST …/issues`), `scripts/lib/spiral-carryover.mjs` `runCli()` (programmatic path), `scripts/lib/issue-budget.mjs` (shared decision core + `resolveMaxPerSession`/`readSessionTypeFromStateMd`), `scripts/lib/issue-budget-reconcile.mjs` (close-time cross-check), `skills/session-end/SKILL.md` Phase 5 Step 3b (overflow drain). Parser: `scripts/lib/config/issue-budget.mjs`.
|
|
282
307
|
|
|
283
308
|
## Slopcheck (Package Legitimacy Gate) (#520)
|
|
284
309
|
|
|
@@ -306,6 +331,8 @@ slopcheck:
|
|
|
306
331
|
| `persistence` | boolean | `true` | Enable session resumption via STATE.md and session memory files. |
|
|
307
332
|
| `memory-cleanup-threshold` | integer | `5` | Recommend `/memory-cleanup` after N accumulated session memory files. |
|
|
308
333
|
| `memory-cleanup-soft-limit` | integer | `180` | Hard ceiling on accumulated memory files before the cleanup nudge escalates from a soft suggestion to a strong recommendation. PRD F2.2 / issue #502. Used by `scripts/lib/auto-dream.mjs`. |
|
|
334
|
+
|
|
335
|
+
**Nudge retirement (2026-09-09, #1246-adjacent).** The two session-end nudges that used to read these thresholds — Phase 3.6.5 Auto-Dream and Phase 3.6.7 Auto-Dialectic — are RETIRED as standalone close-time prompts: measured across consumer repos, the auto-dialectic nudge recorded `decided: true` while nobody ever ran it, and memory-cleanup had run in only 1 of 3 repos, because both fired at the moment the operator is closing down, not the moment they can act. `shouldDispatchAutoDream()` and `shouldDispatchAutoDialectic()` are unchanged as pure signal functions and still consult these two keys — but they are now called from the session-START `maintenance-due` probe (`scripts/lib/maintenance-due-banner.mjs`, see § Reconcile below), which reads them as two of its six signals and reports a single `⚠ maintenance due: N of 6 …` banner at the one moment the operator can actually run `/session housekeeping`.
|
|
309
336
|
| `learning-expiry-days` | integer | `30` | Legacy/default expiry window used by review/extend flows. New analyzer learnings preserve a candidate-supplied `expires_at` or derive expiry from `LEARNING_TTL_DAYS[type]` (for example, `autonomy-verdict` is 90 days). |
|
|
310
337
|
| `learnings-surface-top-n` | integer | `15` | Cap on how many learnings the session-start Phase 5.6 and session-plan Step 0.5 sections surface, ranked by confidence descending. `0` = do not surface any learnings. Applies to Project Intelligence output. |
|
|
311
338
|
| `learning-decay-rate` | float (0.0 ≤ x < 1.0) | `0.05` | Confidence decay applied to every untouched learning at session-end (after touched-set update, before prune). `0.0` = disable decay. A learning starting at `0.5` confidence survives ~10 untouched sessions with default decay. |
|
|
@@ -315,8 +342,8 @@ slopcheck:
|
|
|
315
342
|
| `reasoning-output` | boolean | `false` | Enable STATE:/PLAN: structured reasoning markers in agent prompts. When true, agents emit short transparency lines before tool calls. Opt-in — adds prompt overhead. |
|
|
316
343
|
| `grounding-check` | boolean | `true` | Enable file-level grounding verification in session-end Phase 1.1a (planned vs touched files). When true, session-end compares each agent's declared file scope against `git diff --name-only $SESSION_START_REF..HEAD` and reports scope creep + incomplete coverage. Informational — does not block session close. |
|
|
317
344
|
| `grounding-injection-max-files` | integer | `3` | Max files with recent `edit-format-friction` stagnation history to inject as line-numbered GROUNDING blocks into each agent's prompt before dispatch (wave-executor pre-dispatch step). Per-agent scope; selects top N by recency. `0` disables the feature. Gated on `persistence: true`. (#85) |
|
|
318
|
-
| `isolation` | string | `auto` | Agent isolation mode: `worktree`, `none`, or `auto`. `auto` resolves per-wave via the graduated default (#194): ≤2 agents → `none`, 3–4 agents on feature/deep → `worktree`, ≥5 agents → `worktree`, housekeeping 3–4 → `none`. Explicit `worktree` or `none` overrides the graduation. See [isolation graduation](#isolation-graduation) below. |
|
|
319
|
-
| `max-turns` | integer or string | `auto` | Maximum agent turns before PARTIAL. Auto: housekeeping=8, feature=15, deep=25. |
|
|
345
|
+
| `isolation` | string | `auto` | Agent isolation mode: `worktree`, `none`, or `auto`. `auto` resolves per-wave via the graduated default (#194): ≤2 agents → `none`, 3–4 agents on feature/deep → `worktree`, ≥5 agents → `worktree`, housekeeping 3–4 → `none`. Explicit `worktree` or `none` overrides the graduation. The resolved value surfaces per wave as `waves[].isolation` in the session shape's JSON output (`scripts/session-shape.mjs`) — a coordinator-direct or read-only wave resolves `none` without consulting the graduation at all. See [isolation graduation](#isolation-graduation) below. |
|
|
346
|
+
| `max-turns` | integer or string | `auto` | Maximum agent turns before PARTIAL. Auto expands PER SESSION TYPE inside the resolved shape (`scripts/lib/session-shape.mjs` `MAX_TURNS_DEFAULT`, § Session Shapes above): housekeeping=8, feature=15, deep=25 (`maxTurnsDefault` in the shape JSON, applied to every wave). The `ultradeep` profile does **not** use one flat number — it sets `max-turns` PER WAVE: 40 for the Research+Code-Discovery wave, 25 for Impl-Core/Impl-Polish/Quality, 15 for Release/Finalization (the Synthesis-Gate wave is coordinator-direct and carries no `max-turns` at all). |
|
|
320
347
|
| `auto-commit-per-wave` | boolean | `false` | Automatically commit each wave's work after the Quality-Lite gate passes. Checkpoint commits per wave reduce the risk of data loss from `git stash` collisions in parallel sessions (V3.3 RESCUE incident — see GitLab #214). When `false`, all work is committed at session-end via `/close`. Requires `persistence: true`; the flag is silently ignored when `persistence: false`. Trade-off: each wave produces an additional commit; git log shows N+1 commits instead of 1. Use `/simplify` or `git rebase -i --autosquash` before final close to squash if a clean history is desired. **Implementation note:** the procedural commit sequence (`scripts/lib/auto-commit.mjs`) is deferred to V3.6. Until then, setting this flag to `true` triggers a session-start warning that auto-commits are not yet active — the flag is a no-op but is validated so projects can opt in early. <!-- path-check: historical --> |
|
|
321
348
|
|
|
322
349
|
### enforcement-gates: the five gate keys (#800/#915)
|
|
@@ -588,7 +615,7 @@ This guard converts the manual post-copy `git diff` check (used to rescue the 07
|
|
|
588
615
|
|
|
589
616
|
### Heavy-Repo Preflight (HR-003/HR-004, baseline #60)
|
|
590
617
|
|
|
591
|
-
|
|
618
|
+
The two Session Config fields below apply to repos large enough that default parallelism risks resource pressure (HR-001 indicators: checkout > 50 MB, DB surface > 100 tables, prior parallel agent count > 15, build time > 90s, generated artifacts > 200 MB). The parser accepts both fields; their runtime effects and remaining limits are listed below:
|
|
592
619
|
|
|
593
620
|
| Field | Type | Default | Description |
|
|
594
621
|
|-------|------|---------|-------------|
|
|
@@ -636,7 +663,7 @@ Requires:
|
|
|
636
663
|
|
|
637
664
|
If the fetch fails (network error, auth error, missing file), bootstrap continues without aborting — rules will arrive via the legacy Clank sync path. A warning is printed.
|
|
638
665
|
|
|
639
|
-
See: session-orchestrator issue #110, projects-baseline `docs/REPO-STATUS.md`.
|
|
666
|
+
See: session-orchestrator issue #110, projects-baseline `docs/REPO-STATUS.md`. <!-- path-check: example -->
|
|
640
667
|
|
|
641
668
|
### baseline-project-id
|
|
642
669
|
|
|
@@ -740,7 +767,7 @@ vault-integration:
|
|
|
740
767
|
|
|
741
768
|
> **Host-local override (#653; extended #819).** `vault-dir` resolves host-locally with precedence: env-var (`SO_VAULT_DIR`) > `owner.yaml` `paths.vault-dir` > the committed default. `plan-baseline-path` resolves with an extra per-context tier in between: `SO_BASELINE_PATH` env > `owner.yaml` `baselines:` directory-prefix match against cwd > `owner.yaml` `paths.baseline-path` (legacy scalar) > the committed default. This keeps maintainer-specific absolute paths out of version control. Resolvers: `scripts/lib/config/host-paths.mjs` (both keys) and `scripts/lib/named-baseline-resolver.mjs` (the `baselines:` match tier).
|
|
742
769
|
|
|
743
|
-
> **`SO_CONFIG_HOME` — the host-private config directory itself.** A sibling override, one layer below `owner.yaml`'s own contents rather than a key inside it: `scripts/lib/
|
|
770
|
+
> **`SO_CONFIG_HOME` — the host-private config directory itself.** A sibling override, one layer below `owner.yaml`'s own contents rather than a key inside it: `scripts/lib/config/private-config-dir.mjs` (`resolvePrivateConfigDir()`) is THE resolver (#1223) for the directory holding `owner.yaml`, `host-private.json`, and the host-alias ledger (`SO_HOST_ALIASES_FILE`) — `scripts/lib/host-identity.mjs`'s `_privateDir()` delegates to it — with precedence env-var (`SO_CONFIG_HOME`, names the private dir ITSELF) > `XDG_CONFIG_HOME` (names its PARENT) > the homedir default `~/.config/session-orchestrator`. Both env vars are read with `.trim() || fallback`, not a bare `||` (`.claude/rules/development.md` § Error Handling env-var-fallback-whitespace trap).
|
|
744
771
|
|
|
745
772
|
> **Parser accepts three key-line renderings (#823).** The `vault-integration:` key line is recognized in plain form (`vault-integration:`), dash-bullet form (`- vault-integration:`), and bold-bullet form (`- **vault-integration:**`) — each paired with either the inline-object shape (`{ enabled: true, ... }` on the same line) or the indented block shape shown above. Parser: `scripts/lib/config/vault-integration.mjs` (`_parseVaultIntegration`).
|
|
746
773
|
|
|
@@ -968,7 +995,7 @@ broken-window-budget:
|
|
|
968
995
|
|
|
969
996
|
## Dialectic-Deriver (#506)
|
|
970
997
|
|
|
971
|
-
Opt-in mode for `/evolve --dialectic
|
|
998
|
+
Opt-in mode for `/evolve --dialectic`. When `cadence > 0`, the session-START `maintenance-due` probe reports a due dialectic after every N sessions, and the housekeeping loop runs `/evolve --dialectic --dry-run` to produce a proposed update to USER.md/AGENT.md peer cards (#503). The dry-run writes a sidecar at `.orchestrator/dialectic-pending.md`; the operator applies via `/evolve --dialectic --apply` in a subsequent session. Set `cadence: 0` as a kill-switch. <!-- path-check: example -->
|
|
972
999
|
|
|
973
1000
|
All fields live under a top-level `dialectic` object in your Session Config (CLAUDE.md or AGENTS.md):
|
|
974
1001
|
|
|
@@ -981,15 +1008,15 @@ dialectic:
|
|
|
981
1008
|
|
|
982
1009
|
| Field | Type | Default | Description |
|
|
983
1010
|
|-------|------|---------|-------------|
|
|
984
|
-
| `dialectic.cadence` | integer | `5` | Number of sessions between auto-dialectic dispatches. Set to `0` to disable all dispatches (kill-switch). Non-integer and negative values silently fall back to default. |
|
|
1011
|
+
| `dialectic.cadence` | integer | `5` | Number of sessions between auto-dialectic dispatches. Set to `0` to disable all dispatches (kill-switch). Non-integer and negative values silently fall back to default. **The dispatch moment moved (2026-09-09):** `shouldDispatchAutoDialectic()` is still the decision function this key feeds, but session-end Phase 3.6.7's own auto-trigger nudge is gone — retired as a standalone close-time prompt, and its recording wrapper (with the `orchestrator.dialectic.nudge_decided` event) removed in #1288 — see § Persistence & Safety above "Nudge retirement". The session-start `maintenance-due` probe now calls it as one of six signals, so a due dialectic surfaces where the operator can act on it (session start), not where they are closing down. |
|
|
985
1012
|
| `dialectic.model` | string | `haiku` | Model tier for the critique call. Must be one of `haiku`, `sonnet`, `opus`. **Fail-fast**: unknown values cause parse-config.mjs to exit 1 at startup — NOT silently ignored. |
|
|
986
1013
|
| `dialectic.budget-tokens` | integer | `8000` | Input token budget per call. Output budget is fixed at 4000 (per #506). Non-integer and negative values fall back to default. |
|
|
987
1014
|
|
|
988
|
-
**Used by:** `skills/evolve/SKILL.md` Phase 6, `
|
|
1015
|
+
**Used by:** `skills/evolve/SKILL.md` Phase 6, `scripts/dialectic-deriver.mjs`, `scripts/lib/auto-dialectic.mjs`, and the session-start `maintenance-due` probe (`scripts/lib/maintenance-due-banner.mjs`). Session-end Phase 3.6.7 no longer reads it (retired 2026-09-09).
|
|
989
1016
|
|
|
990
1017
|
**Cross-reference:** PRD F2.5 (#506) — Honcho's "reasoning at consolidation time" insight, adopted without SaaS/AGPL/per-message-LLM-cost.
|
|
991
1018
|
|
|
992
|
-
**
|
|
1019
|
+
**Trigger behavior:** When `cadence > 0` AND sessions-since-last-dialectic ≥ cadence AND (≥1 new session OR ≥1 new learning since last run), `shouldDispatchAutoDialectic()` returns `trigger: true` and the session-start `maintenance-due` probe reports it; the housekeeping session then runs the deriver in dry-run mode (session-end Phase 3.6.7 is retired — it dispatches nothing). The diff sidecar lands at `.orchestrator/dialectic-pending.md` (gitignored, vault-mirror-excluded). When `cadence: 0`, the signal never fires; manual `/evolve --dialectic` always works. <!-- path-check: example -->
|
|
993
1020
|
|
|
994
1021
|
**Token cost:** With defaults (cadence: 5, budget-tokens: 8000, output 4000, model haiku), ~12k tokens every 5 sessions. At haiku pricing this is ~$0.02/run. Surfaced in Final Report.
|
|
995
1022
|
|
|
@@ -997,7 +1024,9 @@ dialectic:
|
|
|
997
1024
|
|
|
998
1025
|
## Eval (#803)
|
|
999
1026
|
|
|
1000
|
-
Opt-in configuration for the Standard v1 evaluation harness
|
|
1027
|
+
Opt-in configuration for the Standard v1 evaluation harness and the `/eval` skill (Session-Prozess-Eval). The current workflow is documented in `skills/eval/SKILL.md`.
|
|
1028
|
+
|
|
1029
|
+
The original config proposal is in the archived PRD `docs/prd/2026-07-16-aiat-llm-eval.md` §S6 (Epic #803). <!-- path-check: historical -->
|
|
1001
1030
|
|
|
1002
1031
|
All fields live under a top-level `eval` object in your Session Config host file (`CLAUDE.md` or `AGENTS.md`), for example:
|
|
1003
1032
|
|
|
@@ -1314,6 +1343,8 @@ Read by: `scripts/lib/config/evolve.mjs` (parser), `skills/evolve/SKILL.md` Step
|
|
|
1314
1343
|
|
|
1315
1344
|
Opt-in configuration for the learning→conditional-rule reconciliation engine (Epic #693). When enabled, the reconciliation engine runs at session-end Phase 3.6.8 and proposes new `.claude/rules/` entries derived from accumulated learnings. The proposal is always operator-AUQ-gated — rules are **never** auto-applied. FA3 (#696) delivers proposals via `AskUserQuestion`; FA4 (#697) adds the guardrail config block documented here. When `enabled: false` (the default), Phase 3.6.8 is a silent no-op and the engine never runs.
|
|
1316
1345
|
|
|
1346
|
+
**The former `reconcile-nudge` session-start probe is SUBSUMED (2026-09-09), not replaced 1:1.** `reconcile-nudge-banner.mjs`'s `computeReconcileNudge()` function is unchanged and still the reconcile-specific signal — but it is no longer surfaced as its own standalone banner. `scripts/lib/maintenance-due-banner.mjs` now calls it wholesale as one of six ANDed maintenance signals (`reconcile: computeReconcileNudge().nudge === true`) behind the single session-start `maintenance-due` probe, alongside `evolve`, `sweep`, `dialectic`, `memory-cleanup` and `pending-sidecar`. The reconcile signal is therefore not lost — it is reported as `⚠ maintenance due: N of 6 (…) — run /session housekeeping.` rather than as its own line, with a 7-day cooldown after any housekeeping session (`HOUSEKEEPING_COOLDOWN_DAYS`) so a repo that just ran the loop stays silent instead of re-nagging.
|
|
1347
|
+
|
|
1317
1348
|
All fields live under a top-level `reconcile` object in your Session Config host file (`CLAUDE.md` or `AGENTS.md`), for example:
|
|
1318
1349
|
|
|
1319
1350
|
```yaml
|
|
@@ -1447,7 +1478,7 @@ frontend-slop-hook:
|
|
|
1447
1478
|
|
|
1448
1479
|
**Used by:** `hooks/post-tooluse-frontend-slop.mjs` (parser/loader: `scripts/lib/config/frontend-slop-hook.mjs`).
|
|
1449
1480
|
|
|
1450
|
-
**Cross-reference:** detector rule markers (`<!-- rule:<id> -->`) live in
|
|
1481
|
+
**Cross-reference:** detector rule markers (`<!-- rule:<id> -->`) live in `rules/opt-in-stack/frontend.md` (Absolute Bans / Motion / Layout sections). Mirrors the opt-in / default-on contrast against `loop-guard`.
|
|
1451
1482
|
|
|
1452
1483
|
## Loop Guard (#619)
|
|
1453
1484
|
|
|
@@ -1593,7 +1624,9 @@ Both variables must be set for the fire-and-forget POST to fire. Setting only `C
|
|
|
1593
1624
|
|
|
1594
1625
|
## Express Path (#214)
|
|
1595
1626
|
|
|
1596
|
-
Codified coordinator-direct flow for housekeeping and simple single-issue sessions. When the express path activates, session-start Phase 8.5 skips
|
|
1627
|
+
Codified coordinator-direct flow for housekeeping and simple single-issue sessions. When the express path activates, session-start Phase 8.5 skips session-plan's full wave decomposition and runs all tasks directly as the coordinator — no subagents dispatched, no inter-wave checkpoints.
|
|
1628
|
+
|
|
1629
|
+
**Relationship to § Session Shapes (2026-09-09).** The 1-wave `coordinator-direct` plan session-plan emits when the express path is active is the SAME shape `resolveSessionShape({sessionType: 'housekeeping'})` now resolves for EVERY housekeeping session, express-path gate or not — a single coordinator-direct "Housekeeping" wave running the maintenance loop (drift-check, sweep, evolve, reconcile, dialectic, memory-cleanup). Express path is the ACTIVATION GATE that decides whether the coordinator runs those tasks inline right now (its 3 conditions below); the housekeeping shape decides the wave STRUCTURE, and is unconditional for the type since the former 3/4/6+-wave role-combination mapping was retired 2026-09-09 for every session type. Housekeeping therefore has no "full 5-wave flow" left to fall back to — see the corrected condition-matrix note below.
|
|
1597
1630
|
|
|
1598
1631
|
> **Historical context:** The 13 coordinator-direct sessions documented in the project `CLAUDE.md` (2026-04 series: vault-mirror GH#31, phased-rollout #307, v3.2.0 release, Architecture-DDD-Trio, etc.) were running this pattern implicitly without a codified path. Issue #214 codifies it so that future housekeeping sessions gain the express path automatically without needing to know to opt in manually.
|
|
1599
1632
|
|
|
@@ -1601,12 +1634,12 @@ All fields live under a top-level `express-path` object in your Session Config h
|
|
|
1601
1634
|
|
|
1602
1635
|
```yaml
|
|
1603
1636
|
express-path:
|
|
1604
|
-
enabled: true # default true; set false to always
|
|
1637
|
+
enabled: true # default true; set false to always run session-plan's full decomposition flow
|
|
1605
1638
|
```
|
|
1606
1639
|
|
|
1607
1640
|
| Field | Type | Default | Description |
|
|
1608
1641
|
|-------|------|---------|-------------|
|
|
1609
|
-
| `express-path.enabled` | boolean | `true` | When `true`, session-start Phase 8.5 evaluates the express-path activation conditions. When `false`, the evaluation is skipped and
|
|
1642
|
+
| `express-path.enabled` | boolean | `true` | When `true`, session-start Phase 8.5 evaluates the express-path activation conditions. When `false`, the evaluation is skipped and session-plan always runs its full decomposition flow — for a housekeeping session that flow still resolves to the same 1-wave shape (§ Session Shapes), since `express-path.enabled` only gates whether the coordinator runs it INLINE right now, not the wave count. |
|
|
1610
1643
|
|
|
1611
1644
|
### Activation conditions
|
|
1612
1645
|
|
|
@@ -1616,7 +1649,7 @@ All three conditions must be true simultaneously for the express path to activat
|
|
|
1616
1649
|
2. Session type is `housekeeping` (confirmed in session-start Phase 8 Q&A)
|
|
1617
1650
|
3. Agreed issue scope is ≤ 3 issues AND no parallel agents are required
|
|
1618
1651
|
|
|
1619
|
-
When any condition is false,
|
|
1652
|
+
**When any condition is false, session-plan runs its full decomposition flow as before** — the express-path check is a transparent no-op on the PLAN, not on the wave shape. For `feature` and `deep` sessions this was always their own resolved shape (3 and 5 waves respectively, per § Session Shapes) and is unaffected by this gate. For a `housekeeping` session that fails the gate (≥4 issues, or parallel agents required), the older documentation here described a fallback to "the full 5-wave flow" — that fallback no longer exists: `resolveSessionShape({sessionType: 'housekeeping'})` returns the same 1-wave coordinator-direct maintenance-loop shape unconditionally, so the practical difference the gate still makes is whether the coordinator executes that one wave INLINE (gate passed) or session-plan emits it as a normal — still 1-wave, still coordinator-direct — plan for wave-executor to run (gate failed).
|
|
1620
1653
|
|
|
1621
1654
|
### What changes when express path is active
|
|
1622
1655
|
|
|
@@ -1629,9 +1662,9 @@ When any condition is false, the full 5-wave flow runs as before — the check i
|
|
|
1629
1662
|
|
|
1630
1663
|
Set `express-path.enabled: false` when:
|
|
1631
1664
|
|
|
1632
|
-
- You want
|
|
1665
|
+
- You want session-plan to emit housekeeping's maintenance-loop wave as a normal wave-executor plan instead of running it inline as the coordinator — the wave STRUCTURE is unchanged either way (§ Session Shapes), only whether it runs inline or through the wave-executor dispatch/checkpoint machinery.
|
|
1633
1666
|
- The session involves ≥ 4 issues (the scope check already prevents activation, but disabling makes the intent explicit).
|
|
1634
|
-
- You are running an automated `/autopilot` loop and want predictable
|
|
1667
|
+
- You are running an automated `/autopilot` loop and want a predictable inline-vs-dispatched execution path across session types.
|
|
1635
1668
|
|
|
1636
1669
|
### Condition matrix
|
|
1637
1670
|
|
|
@@ -1653,7 +1686,7 @@ Set `express-path.enabled: false` when:
|
|
|
1653
1686
|
|
|
1654
1687
|
The `autopilot` block and its single field `autopilot.bg-isolation` are **gone**, not
|
|
1655
1688
|
deprecated. Their only reader was `scripts/autopilot-multi.mjs`, retired together with <!-- path-check: historical -->
|
|
1656
|
-
`commands/autopilot-multi.md` by the 2026-09-06 360°-Audit (§ 5A: 0 telemetry, 0 fleet
|
|
1689
|
+
`commands/autopilot-multi.md` by the 2026-09-06 360°-Audit (§ 5A: 0 telemetry, 0 fleet <!-- path-check: historical -->
|
|
1657
1690
|
invocations in 90 days, no runtime consumer).
|
|
1658
1691
|
|
|
1659
1692
|
Verified 2026-09-06 at `e4674109`:
|