session-orchestrator 3.23.0 → 4.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/architecture/SKILL.md +18 -0
- package/.agents/skills/autopilot/SKILL.md +17 -0
- package/.agents/skills/bootstrap/SKILL.md +20 -0
- package/.agents/skills/brainstorm/SKILL.md +22 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +15 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +22 -0
- package/.agents/skills/debug/SKILL.md +22 -0
- package/.agents/skills/discovery/SKILL.md +20 -0
- package/.agents/skills/dispatcher/SKILL.md +15 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +18 -0
- package/.agents/skills/ecosystem-health/SKILL.md +20 -0
- package/.agents/skills/eli5/SKILL.md +20 -0
- package/.agents/skills/eval/SKILL.md +21 -0
- package/.agents/skills/evolve/SKILL.md +21 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +15 -0
- package/.agents/skills/gitlab-ops/SKILL.md +20 -0
- package/.agents/skills/gitlab-portfolio/SKILL.md +15 -0
- package/.agents/skills/grill/SKILL.md +22 -0
- package/.agents/skills/hook-development/SKILL.md +15 -0
- package/.agents/skills/mcp-builder/SKILL.md +15 -0
- package/.agents/skills/memory-cleanup/SKILL.md +21 -0
- package/.agents/skills/mode-selector/SKILL.md +17 -0
- package/.agents/skills/npm-publish/SKILL.md +16 -0
- package/.agents/skills/peekaboo-driver/SKILL.md +18 -0
- package/.agents/skills/persona-panel/SKILL.md +17 -0
- package/.agents/skills/plan/SKILL.md +20 -0
- package/.agents/skills/playwright-driver/SKILL.md +20 -0
- package/.agents/skills/quality-gates/SKILL.md +20 -0
- package/.agents/skills/reconcile/SKILL.md +21 -0
- package/.agents/skills/remote-offload/SKILL.md +20 -0
- package/.agents/skills/repo-audit/SKILL.md +16 -0
- package/.agents/skills/session-end/SKILL.md +20 -0
- package/.agents/skills/session-plan/SKILL.md +20 -0
- package/.agents/skills/session-start/SKILL.md +20 -0
- package/.agents/skills/spinout/SKILL.md +16 -0
- package/.agents/skills/sunset-review/SKILL.md +16 -0
- package/.agents/skills/test-runner/SKILL.md +20 -0
- package/.agents/skills/tmux-layout/SKILL.md +21 -0
- package/.agents/skills/using-orchestrator/SKILL.md +17 -0
- package/.agents/skills/vault-mirror/SKILL.md +15 -0
- package/.agents/skills/vault-sync/SKILL.md +15 -0
- package/.agents/skills/wave-executor/SKILL.md +20 -0
- package/.agents/skills/write-executable-plan/SKILL.md +22 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/commands/autopilot.md +2 -2
- package/.cursor/commands/bootstrap.md +1 -1
- package/.cursor/commands/brainstorm.md +1 -1
- package/.cursor/commands/debug.md +1 -1
- package/.cursor/commands/discovery.md +1 -1
- package/.cursor/commands/dispatcher.md +2 -2
- package/.cursor/commands/eli5.md +2 -2
- package/.cursor/commands/eval.md +2 -2
- package/.cursor/commands/evolve.md +1 -1
- package/.cursor/commands/go.md +1 -1
- package/.cursor/commands/grill.md +2 -2
- package/.cursor/commands/memory-cleanup.md +2 -2
- package/.cursor/commands/persona-panel.md +1 -1
- package/.cursor/commands/plan.md +1 -1
- package/.cursor/commands/portfolio.md +1 -1
- package/.cursor/commands/reconcile.md +2 -2
- package/.cursor/commands/release.md +2 -2
- package/.cursor/commands/session.md +2 -2
- package/.cursor/commands/spinout.md +2 -2
- package/.cursor/commands/sunset-review.md +2 -2
- package/.cursor/commands/templates-ack.md +2 -2
- package/.cursor/commands/test.md +2 -2
- package/.cursor/skills/brainstorm/SKILL.md +1 -1
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/quality-gates/SKILL.md +1 -1
- package/.cursor/skills/remote-offload/SKILL.md +13 -0
- package/.orchestrator/policy/blocked-commands.json +121 -0
- package/.orchestrator/policy/ecosystem.schema.json +66 -0
- package/.orchestrator/policy/quality-gates.example.json +16 -0
- package/.orchestrator/policy/quality-gates.schema.json +38 -0
- package/.orchestrator/policy/templates-policy.json +27 -0
- package/.orchestrator/policy/test-profiles.json +47 -0
- package/AGENTS.md +225 -0
- package/CHANGELOG.md +1401 -0
- package/NOTICE +11 -6
- package/README.md +127 -92
- package/agents/db-specialist.md +0 -1
- package/agents/eval-judge.md +1 -1
- package/agents/skill-applied-judge.md +1 -1
- package/assets/wave-lifecycle.svg +98 -0
- package/commands/release.md +6 -3
- package/commands/session.md +18 -3
- package/docs/README.md +4 -0
- package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
- package/docs/baseline.md +67 -0
- package/docs/ci-setup.md +249 -48
- package/docs/codex-setup.md +66 -22
- package/docs/components.md +37 -16
- package/docs/cursor-setup.md +6 -2
- package/docs/events-schema.md +51 -10
- package/docs/instruction-delivery.md +62 -0
- package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
- package/docs/migration-v4.md +341 -0
- package/docs/pi-setup.md +6 -1
- package/docs/plugin-architecture-v3.md +1 -1
- package/docs/rule-authoring.md +85 -19
- package/docs/scope-collision-guard.md +8 -8
- package/docs/session-config-reference.md +120 -61
- package/docs/session-config-template.md +40 -33
- package/docs/telemetry/telemetry-claims.md +11 -10
- package/docs/telemetry.md +187 -4
- package/docs/vault-docs-architecture.md +50 -11
- package/hooks/_lib/atomic-json.mjs +111 -0
- package/hooks/_lib/hook-import-set.json +1487 -0
- package/hooks/_lib/subagent-paths.mjs +143 -0
- package/hooks/_lib/subagent-transcript.mjs +562 -0
- package/hooks/config-protection.mjs +2 -2
- package/hooks/cwd-change-restore.mjs +11 -31
- package/hooks/enforce-commands.mjs +69 -0
- package/hooks/enforce-scope.mjs +35 -6
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +10 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/loop-guard.mjs +3 -3
- package/hooks/on-session-end.mjs +280 -14
- package/hooks/on-session-start.mjs +153 -4
- package/hooks/on-stop.mjs +371 -17
- package/hooks/operator-steer.mjs +2 -2
- package/hooks/post-bash-write-verify.mjs +189 -4
- package/hooks/post-edit-import-probe.mjs +344 -0
- package/hooks/post-subagent-discovery-validator.mjs +278 -392
- package/hooks/post-tool-batch-wave-signal.mjs +272 -44
- package/hooks/post-tool-failure-corrective-context.mjs +11 -34
- package/hooks/post-tooluse-frontend-slop.mjs +3 -3
- package/hooks/pre-bash-destructive-guard.mjs +39 -13
- package/hooks/pre-bash-memory-propose-audit.mjs +13 -7
- package/hooks/skill-invocation-telemetry.mjs +17 -5
- package/hooks/subagent-telemetry.mjs +24 -30
- package/monitors/monitors.json +3 -3
- package/package.json +9 -1
- package/pi/prompts/session.md +2 -2
- package/plugin.json +27 -0
- package/scripts/autopilot.mjs +26 -12
- package/scripts/backfill-abandoned-sessions.mjs +130 -15
- package/scripts/backfill-learnings-from-vault.mjs +9 -3
- package/scripts/dialectic-deriver.mjs +73 -8
- package/scripts/emit-event.mjs +10 -2
- package/scripts/export-hw-learnings.mjs +113 -1
- package/scripts/generate-agents-skills.mjs +378 -0
- package/scripts/generate-cursor-adapter.mjs +45 -8
- package/scripts/generate-hook-import-set.mjs +249 -0
- package/scripts/lib/agent-status.mjs +13 -2
- package/scripts/lib/auq/parse.mjs +5 -29
- package/scripts/lib/auto-dialectic.mjs +68 -0
- package/scripts/lib/auto-dream.mjs +38 -36
- package/scripts/lib/autonomy/suitability.mjs +6 -0
- package/scripts/lib/autopilot/loop.mjs +2 -2
- package/scripts/lib/autopilot/worktree-pipeline.mjs +82 -6
- package/scripts/lib/build-live-signals.mjs +25 -22
- package/scripts/lib/ci-status-banner.mjs +220 -75
- package/scripts/lib/codex/plugin-contract.mjs +82 -6
- package/scripts/lib/cold-start-detector.mjs +23 -14
- package/scripts/lib/config/auto-dream.mjs +2 -1
- package/scripts/lib/config/block-header.mjs +63 -0
- package/scripts/lib/config/block-preprocess.mjs +177 -0
- package/scripts/lib/config/broken-window.mjs +2 -1
- package/scripts/lib/config/cold-start.mjs +2 -1
- package/scripts/lib/config/config-protection.mjs +22 -2
- package/scripts/lib/config/context-coverage.mjs +2 -1
- package/scripts/lib/config/cross-repo.mjs +2 -1
- package/scripts/lib/config/custom-phases.mjs +2 -1
- package/scripts/lib/config/dialectic.mjs +2 -1
- package/scripts/lib/config/discovery-validator.mjs +9 -3
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
- package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
- package/scripts/lib/config/docs-orchestrator.mjs +2 -1
- package/scripts/lib/config/docs-staleness.mjs +2 -1
- package/scripts/lib/config/drift-check.mjs +2 -1
- package/scripts/lib/config/eval.mjs +2 -1
- package/scripts/lib/config/events-rotation.mjs +2 -1
- package/scripts/lib/config/evolve.mjs +8 -2
- package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
- package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
- package/scripts/lib/config/handover-gate.mjs +2 -1
- package/scripts/lib/config/health-endpoints.mjs +388 -0
- package/scripts/lib/config/issue-budget.mjs +2 -1
- package/scripts/lib/config/loop-guard.mjs +2 -1
- package/scripts/lib/config/memory.mjs +2 -1
- package/scripts/lib/config/moc-staleness.mjs +2 -1
- package/scripts/lib/config/persona-gate-wave.mjs +2 -1
- package/scripts/lib/config/private-config-dir.mjs +67 -0
- package/scripts/lib/config/reconcile.mjs +2 -1
- package/scripts/lib/config/remote-hosts.mjs +234 -0
- package/scripts/lib/config/section-extractor.mjs +7 -1
- package/scripts/lib/config/skill-evolution.mjs +2 -1
- package/scripts/lib/config/slopcheck.mjs +2 -1
- package/scripts/lib/config/state-md-lock.mjs +2 -1
- package/scripts/lib/config/templates-first.mjs +2 -1
- package/scripts/lib/config/test.mjs +2 -1
- package/scripts/lib/config/vault-integration.mjs +7 -1
- package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
- package/scripts/lib/config/vault-staleness.mjs +2 -1
- package/scripts/lib/config/vault-sync.mjs +2 -1
- package/scripts/lib/config/verification-auto-fix.mjs +2 -1
- package/scripts/lib/config/wave-reviewers.mjs +2 -1
- package/scripts/lib/config/worktree-orphans.mjs +2 -1
- package/scripts/lib/config.mjs +31 -3
- package/scripts/lib/convergence-monitor.mjs +82 -16
- package/scripts/lib/dispatcher/enumerate.mjs +2 -17
- package/scripts/lib/dispatcher/rank.mjs +124 -48
- package/scripts/lib/ecosystem-health.mjs +16 -2
- package/scripts/lib/eval/engine.mjs +9 -1
- package/scripts/lib/eval/session-resolve.mjs +23 -4
- package/scripts/lib/events-schema.mjs +48 -0
- package/scripts/lib/events.mjs +256 -7
- package/scripts/lib/evolve/autonomy-verdict.mjs +9 -4
- package/scripts/lib/evolve/autopilot-effectiveness.mjs +18 -1
- package/scripts/lib/frontmatter-guard.mjs +131 -13
- package/scripts/lib/gates/gate-full.mjs +26 -0
- package/scripts/lib/gates/gate-helpers.mjs +76 -0
- package/scripts/lib/gitlab-portfolio/cli.mjs +3 -15
- package/scripts/lib/hardware-pattern-detector.mjs +18 -1
- package/scripts/lib/harness-audit/categories/category1.mjs +17 -6
- package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
- package/scripts/lib/host-identity.mjs +50 -11
- package/scripts/lib/instruction-budget-guard.mjs +171 -5
- package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
- package/scripts/lib/learnings/io.mjs +60 -6
- package/scripts/lib/memory-banner.mjs +20 -8
- package/scripts/lib/memory-proposals/store.mjs +30 -22
- package/scripts/lib/owner-config-banner.mjs +43 -6
- package/scripts/lib/owner-config-loader.mjs +21 -10
- package/scripts/lib/owner-interview.mjs +3 -3
- package/scripts/lib/owner-yaml.mjs +207 -14
- package/scripts/lib/peer-discovery.mjs +20 -2
- package/scripts/lib/platform.mjs +108 -15
- package/scripts/lib/plugin-update-banner.mjs +406 -0
- package/scripts/lib/project-hygiene.mjs +38 -2
- package/scripts/lib/qg-command-drift-banner.mjs +50 -12
- package/scripts/lib/quality-gate.mjs +133 -44
- package/scripts/lib/reconcile/emitter.mjs +68 -6
- package/scripts/lib/reconcile/engine.mjs +249 -9
- package/scripts/lib/reconcile/idempotency.mjs +37 -4
- package/scripts/lib/reconcile/writer.mjs +40 -18
- package/scripts/lib/scope-gate.mjs +36 -0
- package/scripts/lib/session-close-backfill.mjs +125 -18
- package/scripts/lib/session-discovery.mjs +57 -3
- package/scripts/lib/session-end/phase-skip.mjs +2 -2
- package/scripts/lib/session-id.mjs +12 -23
- package/scripts/lib/session-identity/own-session.mjs +187 -11
- package/scripts/lib/session-lock-shape.mjs +43 -0
- package/scripts/lib/session-lock.mjs +5 -10
- package/scripts/lib/session-registry.mjs +25 -9
- package/scripts/lib/session-schema/constants.mjs +36 -2
- package/scripts/lib/session-schema/validator.mjs +38 -4
- package/scripts/lib/session-start-probes.mjs +18 -1
- package/scripts/lib/session-transition.mjs +1 -1
- package/scripts/lib/sessions-canonical.mjs +446 -0
- package/scripts/lib/sessions-staleness-banner.mjs +18 -11
- package/scripts/lib/skill-health/join.mjs +17 -4
- package/scripts/lib/state-md.mjs +78 -0
- package/scripts/lib/sunset/walker.mjs +6 -0
- package/scripts/lib/telemetry/schema.mjs +255 -17
- package/scripts/lib/telemetry/sync.mjs +417 -24
- package/scripts/lib/tmux-layout/telemetry.mjs +14 -2
- package/scripts/lib/validate/check-agents-skills.mjs +327 -0
- package/scripts/lib/validate/check-agents.mjs +3 -3
- package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
- package/scripts/lib/validate/check-doc-cli-commands.mjs +9 -33
- package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +370 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
- package/scripts/lib/validate/check-owner-leakage.mjs +281 -20
- package/scripts/lib/validate/check-skill-links.mjs +163 -0
- package/scripts/lib/validate/check-skill-script-paths.mjs +455 -0
- package/scripts/lib/validate/check-untracked-test-deps.mjs +10 -0
- package/scripts/lib/validate/check-unwired-features.mjs +0 -9
- package/scripts/lib/validate/check-validator-registration.mjs +254 -0
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +6 -28
- package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
- package/scripts/lib/validate/markdown-fences.mjs +196 -0
- package/scripts/lib/vault-backfill/template.mjs +63 -6
- package/scripts/lib/vault-mirror/process.mjs +165 -42
- package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
- package/scripts/lib/vault-status/board-lock.mjs +185 -0
- package/scripts/lib/vault-status/board-writer.mjs +174 -135
- package/scripts/lib/vault-status/narrative-mirror.mjs +129 -37
- package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
- package/scripts/lib/wave-executor/remote-dispatch.mjs +502 -0
- package/scripts/lib/wave-resource-gate.mjs +133 -7
- package/scripts/lib/wave-sizing.mjs +4 -1
- package/scripts/lib/wave-transcript-tail.mjs +142 -8
- package/scripts/materialize-wave-scope.mjs +32 -9
- package/scripts/memory-propose.mjs +146 -8
- package/scripts/migrate-cold-start-seed.mjs +4 -1
- package/scripts/parse-config.mjs +60 -3
- package/scripts/promote-vault-strict.mjs +4 -15
- package/scripts/release.mjs +337 -29
- package/scripts/repair-invalid-sessions.mjs +3 -3
- package/scripts/run-quality-gate.mjs +128 -11
- package/scripts/site-numbers.mjs +36 -4
- package/scripts/sweep-expired-learnings.mjs +90 -0
- package/scripts/sync-vault-schema.mjs +3 -1
- package/scripts/telemetry.mjs +2 -2
- package/scripts/validate-plugin.mjs +187 -0
- package/scripts/validate-wave-scope.mjs +28 -8
- package/scripts/vault-consolidate.mjs +3 -11
- package/scripts/vault-integration-watcher.mjs +2 -4
- package/scripts/vault-mirror.mjs +111 -26
- package/scripts/wave-scope-binding.mjs +215 -0
- package/skills/_shared/instruction-file-resolution.md +10 -0
- package/skills/_shared/parallel-aware-auq.md +31 -2
- package/skills/_shared/parallel-aware-preamble.md +18 -4
- package/skills/_shared/platform-tools.md +1 -1
- package/skills/_shared/state-ownership.md +1 -1
- package/skills/architecture/SKILL.md +7 -5
- package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
- package/skills/autopilot/SKILL.md +4 -18
- package/skills/claude-md-drift-check/SKILL.md +5 -1
- package/skills/claude-md-drift-check/checker.mjs +62 -2
- package/skills/convergence-monitoring/SIGNALS.md +55 -0
- package/skills/discovery/probes/vault-staleness.mjs +37 -13
- package/skills/discovery/probes-arch.md +20 -18
- package/skills/dispatcher/SKILL.md +3 -2
- package/skills/ecosystem-health/SKILL.md +4 -1
- package/skills/ecosystem-health/wizard.md +5 -0
- package/skills/evolve/SKILL.md +87 -11
- package/skills/frontmatter-guard/SKILL.md +11 -5
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +38 -2
- package/skills/remote-offload/SKILL.md +89 -0
- package/skills/session-end/SKILL.md +18 -905
- package/skills/session-end/phase-3-6-tail.md +19 -9
- package/skills/session-end/plan-verification.md +221 -155
- package/skills/session-end/references/phase-2-quality-gate.md +93 -0
- package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
- package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
- package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
- package/skills/session-end/references/session-summary-template.md +62 -0
- package/skills/session-plan/SKILL.md +49 -0
- package/skills/session-start/SKILL.md +41 -900
- package/skills/session-start/phase-8-5-express-path.md +1 -1
- package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
- package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
- package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
- package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
- package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
- package/skills/session-start/references/phase-4-ssot-environment-check.md +155 -0
- package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
- package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
- package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
- package/skills/vault-sync/validator.mjs +21 -27
- package/skills/wave-executor/SKILL.md +16 -2
- package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
- package/skills/wave-executor/references/wave-loop-review.md +570 -0
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
- package/skills/wave-executor/wave-loop.md +14 -1271
- package/templates/_shared/journey-manifest.md +10 -6
- package/.cursor/commands/autopilot-multi.md +0 -14
- package/.cursor/commands/contract-version-bump.md +0 -14
- package/.cursor/commands/journey-audit.md +0 -14
- package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
- package/.cursor/skills/daily/SKILL.md +0 -12
- package/.cursor/skills/domain-model/SKILL.md +0 -13
- package/.cursor/skills/journey-audit/SKILL.md +0 -13
- package/.cursor/skills/skill-creator/SKILL.md +0 -13
- package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
- package/commands/autopilot-multi.md +0 -74
- package/commands/contract-version-bump.md +0 -28
- package/commands/journey-audit.md +0 -43
- package/pi/prompts/autopilot-multi.md +0 -12
- package/pi/prompts/contract-version-bump.md +0 -12
- package/pi/prompts/journey-audit.md +0 -12
- package/scripts/autopilot-multi.mjs +0 -885
- package/scripts/backfill-learnings-expires.mjs +0 -196
- package/scripts/backfill-learnings.mjs +0 -203
- package/scripts/fleet-instruction-scan.mjs +0 -141
- package/scripts/lib/autopilot/dep-graph.mjs +0 -417
- package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
- package/scripts/lib/webhook-url.mjs +0 -105
- package/scripts/lifecycle-sim-v6.mjs +0 -347
- package/scripts/migrate-learnings-jsonl.mjs +0 -189
- package/scripts/migrate-subagents-jsonl.mjs +0 -196
- package/scripts/upload-social-preview.mjs +0 -316
- package/skills/_shared/model-selection.md +0 -64
- package/skills/contract-version-bump/SKILL.md +0 -219
- package/skills/daily/SKILL.md +0 -222
- package/skills/daily/generate.sh +0 -92
- package/skills/daily/templates/daily.md.tpl +0 -36
- package/skills/journey-audit/SKILL.md +0 -269
- package/skills/skill-creator/SKILL.md +0 -168
- package/skills/ubiquitous-language/SKILL.md +0 -97
- package/skills/vault-sync/package-lock.json +0 -40
- /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
- /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
package/commands/session.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Start a development session (housekeeping, feature, deep)
|
|
3
|
-
argument-hint: "[housekeeping|feature|deep]"
|
|
2
|
+
description: Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)
|
|
3
|
+
argument-hint: "[housekeeping|feature|deep|ultradeep]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Session Start
|
|
@@ -9,7 +9,22 @@ You are beginning a new development session. The user has invoked `/session` wit
|
|
|
9
9
|
|
|
10
10
|
**Default rationale (measured, not assumed):** `deep` is the default because it is what operators actually run — 77.3 % of 489 recorded sessions across 5 repos, and 115 of 228 (50.4 %) in this repo's own `.orchestrator/metrics/sessions.jsonl`. The former `feature` default made the majority case the one that had to be typed out every time. A `deep` default costs a downgrade keystroke in the minority case; a `feature` default cost an upgrade keystroke in the majority case.
|
|
11
11
|
|
|
12
|
-
**Argument validation:** Valid session types are `housekeeping`, `feature`, and `deep`. An explicit `$ARGUMENTS` value ALWAYS wins over the default — `/session housekeeping` and `/session feature` behave exactly as before. If `$ARGUMENTS` is not empty and does not match any valid type, inform the user: "Invalid session type '$ARGUMENTS'. Valid types: housekeeping, feature, deep." Then fall back to `deep`.
|
|
12
|
+
**Argument validation:** Valid session types are `housekeeping`, `feature`, and `deep`. An explicit `$ARGUMENTS` value ALWAYS wins over the default — `/session housekeeping` and `/session feature` behave exactly as before. `ultradeep` is additionally accepted as an ARGUMENT ALIAS (see below); it is not a fourth type. If `$ARGUMENTS` is not empty and does not match any valid type or the alias, inform the user: "Invalid session type '$ARGUMENTS'. Valid types: housekeeping, feature, deep (alias: ultradeep)." Then fall back to `deep`.
|
|
13
|
+
|
|
14
|
+
### Argument alias: `ultradeep` (PRD `docs/prd/2026-09-06-ultradeep-session-profile.md`)
|
|
15
|
+
|
|
16
|
+
`/session ultradeep` is an alias, NOT a fourth `session_type`. Resolve it to TWO STATE.md frontmatter values and then continue exactly as a `deep` session would:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
session-type: deep # what every downstream consumer sees
|
|
20
|
+
session-profile: ultradeep # the only place the alias survives
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- **`session-type` NEVER becomes `ultradeep`.** The value is a closed set in `scripts/lib/session-schema/constants.mjs` (`VALID_SESSION_TYPES`) and in `scripts/lib/wave-sizing.mjs`; a fourth member would degrade silently in two places (`scripts/lib/telemetry/schema.mjs` maps an unknown type to `"other"`, `scripts/lib/session-close-backfill.mjs` labels it `housekeeping`). The alias exists so that no closed set has to change.
|
|
24
|
+
- **`session-profile` is optional and absent by default.** A plain `/session deep` writes NO `session-profile` key. Absent means "no profile" — never write an empty string, `none`, or `null` to mean absence. Read/write helpers: `readSessionProfile` / `setSessionProfile` in `scripts/lib/state-md.mjs`.
|
|
25
|
+
- **What the profile changes** is the WAVE SHAPE, not the session type: 7 waves with a coordinator-direct Synthesis-Gate at wave 2. See `skills/session-plan/SKILL.md` § Role-to-Wave Mapping and `skills/wave-executor/SKILL.md` § Ultradeep Profile.
|
|
26
|
+
- **Precondition.** The profile needs 7 waves. If Session Config sets `waves` below 7, do NOT silently plan 5 waves under an ultradeep label — name the conflict to the user and let them raise `waves` or drop the alias.
|
|
27
|
+
- **Budgets are deliberately not implemented yet** (PRD § 7): no `ultradeep.max-*` key is read anywhere. Do not invent one; the PRD defers thresholds until three runs have been measured.
|
|
13
28
|
|
|
14
29
|
> **Not read from Session Config.** There is deliberately no `session-type:` (or equivalent) key in the `## Session Config` block — `scripts/lib/config.mjs` `parseSessionConfig()` does not emit one, so any such key in a repo's CLAUDE.md (or its Codex CLI equivalent AGENTS.md) is inert prose. The `session-type:` scalar that IS live lives in STATE.md frontmatter (read by `scripts/print-applicable-rules.mjs` for rule mode-gating) and is written per session, not configured per repo. Do not reintroduce a Session Config key here without wiring it into the parser first.
|
|
15
30
|
|
package/docs/README.md
CHANGED
|
@@ -98,6 +98,10 @@ Two things worth knowing about this split:
|
|
|
98
98
|
| `docs/plans/` | Active work document | `/write-executable-plan` artifacts for in-progress work. May not exist when nothing is mid-plan. |
|
|
99
99
|
| `docs/_private/`, `docs/specs/` | Local-only (gitignored) | Operator scratch space; never tracked, out of scope for this classification. |
|
|
100
100
|
|
|
101
|
+
### Superseded design notes
|
|
102
|
+
|
|
103
|
+
Because `docs/specs/` is gitignored, a correction written INTO a spec can never be committed — so the correction lives here instead. `docs/specs/2026-05-26-parallel-aware-sessions-design.md` (parallel-aware sessions) specifies PID-based lock liveness (`stale-pid-dead`). That is **superseded**: liveness is heartbeat-age based since #1137 (`isLockLive`; `acquire()` knows only `stale-heartbeat`), and the recorded PID is consulted nowhere since #1151 — it was the PID of the short-lived subprocess that wrote the lock, dead within a second. Read the local spec only with that correction applied.
|
|
104
|
+
|
|
101
105
|
## See Also
|
|
102
106
|
|
|
103
107
|
- `docs/prd/2026-07-08-docs-public-split.md` — the epic that established this split (S1–S8, issues #775–#782).
|
|
@@ -1,37 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
name: agents-authoring-spec
|
|
3
|
-
description: NOT A DISPATCHABLE AGENT — never select this. It is the authoring specification that the agent definitions in this directory must follow, loaded as a nested instruction file. Claude Code's plugin loader registers every agents/*.md as an agent by directory convention, and the manifest's `agents` key is additive-only, so it cannot exclude a path. Without this frontmatter the file registered as an unnamed agent with FULL tool access; the minimal `tools` line below is what bounds that. If you need agent-authoring rules, read this file — do not dispatch it.
|
|
4
|
-
tools: Read
|
|
5
|
-
---
|
|
1
|
+
<!-- Moved in v4.0.0 from `agents/AGENTS.md` (audit 2026-09-06 § 5A). It never was an agent: Claude Code's plugin loader registers every `agents/*.md` by directory convention and the manifest's `agents` key is additive-only, so no manifest entry could exclude it — only pseudo-frontmatter (`name: agents-authoring-spec`, `tools: Read`) kept the false registration bounded. Living under `docs/` removes the registration instead of bounding it. -->
|
|
6
2
|
|
|
7
|
-
#
|
|
3
|
+
# Sub-Agent Authoring Conventions (`agents/**`)
|
|
8
4
|
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
> conventions). Resolution rule:
|
|
5
|
+
> Authoring spec for the sub-agent definitions in `agents/`. Read it together
|
|
6
|
+
> with the root `CLAUDE.md` (big picture) and, when working under `agents/`,
|
|
7
|
+
> whatever nested instruction file that subtree carries. Resolution rule:
|
|
13
8
|
> [`../skills/_shared/instruction-file-resolution.md`](../skills/_shared/instruction-file-resolution.md).
|
|
14
9
|
>
|
|
15
|
-
> This
|
|
16
|
-
>
|
|
17
|
-
>
|
|
18
|
-
>
|
|
19
|
-
>
|
|
20
|
-
>
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
24
|
-
>
|
|
25
|
-
>
|
|
26
|
-
>
|
|
27
|
-
>
|
|
28
|
-
> `tools` at `Read`. Do not remove it — and if you add another non-agent doc to
|
|
29
|
-
> this directory, give it the same treatment.
|
|
10
|
+
> **This spec lives in `docs/`, not in `agents/`, on purpose.** Claude Code's
|
|
11
|
+
> plugin loader registers every `agents/*.md` as a dispatchable agent by
|
|
12
|
+
> directory convention, and the manifest's `agents` key is documented as
|
|
13
|
+
> *additive* ("in addition to those in the `agents/` directory"), so it cannot
|
|
14
|
+
> exclude a path. As `agents/AGENTS.md` this file was therefore a registered
|
|
15
|
+
> agent — first an unnamed one with **full tool access**, later a contained one
|
|
16
|
+
> whose pseudo-frontmatter capped `tools` at `Read`. Moving it out of the
|
|
17
|
+
> directory removes the registration rather than bounding it. The same applies
|
|
18
|
+
> to any future non-agent doc: put it under `docs/`, never in `agents/`.
|
|
19
|
+
> (`scripts/lib/validate/check-agents.mjs` still excludes `AGENTS.md` /
|
|
20
|
+
> `CLAUDE.md` by name, and `measureDescriptionSurface` still excludes them from
|
|
21
|
+
> its walked corpus (#878) — both now vacuous for this file, and the safety net
|
|
22
|
+
> for anyone who reintroduces one.)
|
|
30
23
|
>
|
|
31
24
|
> Sibling spec: for `.claude/rules/*.md` frontmatter (conditional loading via
|
|
32
25
|
> globs/mode/host-class/expiry, plus the never-always-on invariant for
|
|
33
26
|
> auto-generated rules), see the canonical authoring spec
|
|
34
|
-
> [`docs/rule-authoring.md`](
|
|
27
|
+
> [`docs/rule-authoring.md`](./rule-authoring.md).
|
|
35
28
|
|
|
36
29
|
## Local Validation Commands
|
|
37
30
|
|
package/docs/baseline.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# The projects-baseline Relationship
|
|
2
|
+
|
|
3
|
+
**One line:** `projects-baseline` is a **private, optional** companion repository that
|
|
4
|
+
holds the operator's canonical rule and schema corpus. session-orchestrator reads
|
|
5
|
+
from it when it is present and degrades to a documented fallback when it is not.
|
|
6
|
+
Nothing in this plugin requires it, and no public consumer needs to obtain it.
|
|
7
|
+
|
|
8
|
+
## What it is
|
|
9
|
+
|
|
10
|
+
A separate git repository (not vendored, not a submodule, not on npm) carrying:
|
|
11
|
+
|
|
12
|
+
- `packages/zod-schemas/src/vault-frontmatter.ts` — the canonical Zod schema for
|
|
13
|
+
Obsidian vault note frontmatter.
|
|
14
|
+
- `templates/shared/.vault.yaml.template` — the canonical `.vault.yaml` template.
|
|
15
|
+
- A `.claude/rules/` corpus. Measured: **26 rule files, all using `paths:`
|
|
16
|
+
frontmatter, 0 using `globs:`** (`scripts/lib/rule-loader.mjs` module doc;
|
|
17
|
+
restated in `scripts/lib/validate/check-rules.mjs`). That corpus is the reason
|
|
18
|
+
`paths:` exists as a same-shape alias for `globs:` at all (#795) — the fleet's
|
|
19
|
+
rules are read **from the baseline**, not from this plugin, so the plugin had to
|
|
20
|
+
learn the baseline's frontmatter convention rather than the other way round.
|
|
21
|
+
|
|
22
|
+
## How the plugin finds it
|
|
23
|
+
|
|
24
|
+
Never by a hardcoded path. Resolution is host-local, most specific first:
|
|
25
|
+
|
|
26
|
+
1. `SO_BASELINE_PATH` environment variable
|
|
27
|
+
2. `owner.yaml` `paths.baseline-path` (`~/.config/session-orchestrator/owner.yaml`,
|
|
28
|
+
host-local, never committed — see `docs/owner-config-schema.md`)
|
|
29
|
+
3. a sibling checkout at `<repoRoot>/../projects-baseline`
|
|
30
|
+
4. `~/Projects/projects-baseline` (legacy default)
|
|
31
|
+
|
|
32
|
+
Tiers 1–2 go through `resolveHostPath('baseline-path', …)` in
|
|
33
|
+
`scripts/lib/config/host-paths.mjs`. `scripts/lib/vault-backfill/template.mjs`
|
|
34
|
+
additionally honours `PROJECTS_BASELINE_DIR` above all four, for back-compat.
|
|
35
|
+
|
|
36
|
+
## The four hard-runtime touchpoints, and what each degrades to
|
|
37
|
+
|
|
38
|
+
| Touchpoint | Reads / writes | Without a baseline |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `scripts/lib/frontmatter-guard.mjs` | the canonical vault-frontmatter Zod schema | `readVaultSchema()` → `null`; `generateFrontmatterSnippet()` falls back to an in-module enum set mirroring `skills/vault-sync/validator.mjs` and warns ONCE on stderr; `computeSchemaHash()` → `null` (never the empty-string hash) |
|
|
41
|
+
| `scripts/lib/vault-backfill/template.mjs` | `.vault.yaml.template` | `loadTemplate()` calls `dieFn(2, …)` with a message naming `owner.yaml paths.baseline-path`, `SO_BASELINE_PATH`, `PROJECTS_BASELINE_DIR`, and the sibling-checkout convention. Only `scripts/vault-backfill.mjs` is affected; nothing else aborts |
|
|
42
|
+
| `scripts/sync-vault-schema.mjs` | `--check` drift guard against the canonical schema | exits 2 (missing file). It is a maintenance script, never on a session path |
|
|
43
|
+
| `scripts/lib/reconcile/writer.mjs` + `scripts/lib/session-end/phase-skip.mjs` | writes rule proposals into the baseline (`reconcile.targets` containing `baseline`) | `baselineRoot` absent ⇒ the `baseline` target is a **no-op**; `repo-local` (the default target) is unaffected |
|
|
44
|
+
|
|
45
|
+
`scripts/promote-vault-strict.mjs` also uses a baseline template and already ships
|
|
46
|
+
an explicit `--no-baseline` opt-out.
|
|
47
|
+
|
|
48
|
+
## The public fallback
|
|
49
|
+
|
|
50
|
+
A repository bootstrapped without the baseline is a normal, supported outcome —
|
|
51
|
+
`skills/bootstrap/public-fallback.md` owns that path. `bootstrap.lock` records
|
|
52
|
+
which source produced the scaffold in its `source:` field:
|
|
53
|
+
|
|
54
|
+
- `claude-init` — `claude init` ran successfully (Claude Code fast path)
|
|
55
|
+
- `plugin-template` — the plugin's own template was copied (every other case)
|
|
56
|
+
- `projects-baseline` — the private baseline was present and used
|
|
57
|
+
|
|
58
|
+
The first two are the **public** values. A consumer repo that shows either is
|
|
59
|
+
fully bootstrapped; the baseline adds the operator's private corpus on top, it
|
|
60
|
+
does not gate the scaffold.
|
|
61
|
+
|
|
62
|
+
## See also
|
|
63
|
+
|
|
64
|
+
- `docs/owner-config-schema.md` — `owner.yaml` schema, including `paths.baseline-path`
|
|
65
|
+
- `docs/rule-authoring.md` — `paths:` / `globs:` frontmatter
|
|
66
|
+
- `skills/bootstrap/public-fallback.md` — the no-baseline bootstrap path
|
|
67
|
+
- `skills/frontmatter-guard/SKILL.md` — the schema-source resolution table
|
package/docs/ci-setup.md
CHANGED
|
@@ -14,25 +14,124 @@ project-level Job Token allowlists are explicitly configured — an admin action
|
|
|
14
14
|
in the foreign project that cannot be scripted from here. The fix is a deploy
|
|
15
15
|
token or PAT stored as the masked CI variable `SCHEMA_DRIFT_TOKEN`.
|
|
16
16
|
|
|
17
|
-
> **
|
|
18
|
-
> `
|
|
19
|
-
> `
|
|
20
|
-
>
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
24
|
-
>
|
|
25
|
-
>
|
|
26
|
-
>
|
|
27
|
-
>
|
|
28
|
-
>
|
|
29
|
-
>
|
|
17
|
+
> **Armed (2026-09-03, #1175): the hard gate is live.** #531 landed upstream
|
|
18
|
+
> — `infrastructure/projects-baseline` commit `cb9ec97` adds `peer-card`,
|
|
19
|
+
> `board`, and `source-repo` to the canonical schema (the issue's AC named
|
|
20
|
+
> only `peer-card`; the close comment widened scope to all three values
|
|
21
|
+
> already vendored ahead here). That closed the vendored-schema divergence
|
|
22
|
+
> which had blocked activation since 2026-09-02; `skills/vault-sync/
|
|
23
|
+
> validator.mjs` was regenerated and `node scripts/sync-vault-schema.mjs
|
|
24
|
+
> --check` now exits 0. The Project Access Token was re-minted (id 53, see
|
|
25
|
+
> § Activation status below), the masked `SCHEMA_DRIFT_TOKEN` CI variable is
|
|
26
|
+
> set on this project, and `SCHEMA_DRIFT_OPTIONAL` is `"false"` at both
|
|
27
|
+
> sites in `.gitlab-ci.yml` — a missing or expired token now hard-fails the
|
|
28
|
+
> pipeline (exit 4) instead of printing the amber `NOT VERIFIED` line that
|
|
29
|
+
> was the accepted state under the prior (2026-08-28, #1062) decision. Both
|
|
30
|
+
> directions were proven before the flip — see below. Revisit trigger for
|
|
31
|
+
> the token itself: expiry (2027-09-01) or a scope/rotation need — see
|
|
32
|
+
> § Rotation / re-arm sequence.
|
|
33
|
+
|
|
34
|
+
### Activation status (token re-minted 2026-09-03, id 53)
|
|
35
|
+
|
|
36
|
+
The Project Access Token was revoked on 2026-09-02 once a control run had
|
|
37
|
+
answered the question it was minted for — an unused credential is a
|
|
38
|
+
liability per SEC-005's secrets-lifecycle discipline. That control run had
|
|
39
|
+
also surfaced the real reason activation was still blocked:
|
|
40
|
+
`skills/vault-sync/validator.mjs`'s `vaultNoteTypeSchema` enum carried
|
|
41
|
+
`peer-card` and `board`, and `vaultFrontmatterSchema` carried
|
|
42
|
+
`source-repo: z.string().optional()`, none of which the canonical
|
|
43
|
+
`infrastructure/projects-baseline` source had yet — the documented
|
|
44
|
+
vendor-ahead state (`scripts/sync-vault-schema.mjs` header, "Vendor-ahead
|
|
45
|
+
state (2026-05-23, #503, I5)"), tracked as upstream-sync-debt in issue #531
|
|
46
|
+
(#503 itself was already closed).
|
|
47
|
+
|
|
48
|
+
**#531 landed upstream** as commit `cb9ec97`: `vaultNoteTypeSchema` gained
|
|
49
|
+
`peer-card` and `board`; `vaultFrontmatterSchema` gained `source-repo:
|
|
50
|
+
z.string().optional()`. With the canonical source caught up,
|
|
51
|
+
`node scripts/sync-vault-schema.mjs --check` exits 0 — no drift.
|
|
52
|
+
|
|
53
|
+
**Token, re-minted:**
|
|
54
|
+
|
|
55
|
+
- **Name:** `session-orchestrator-ci-schema-drift`
|
|
56
|
+
- **Project:** `infrastructure/projects-baseline` (id 52) — the TARGET repo,
|
|
57
|
+
not this one
|
|
58
|
+
- **Token id:** 53
|
|
59
|
+
- **Scopes:** `read_repository`
|
|
60
|
+
- **Access level:** Reporter (20)
|
|
61
|
+
- **Expires:** 2027-09-01
|
|
62
|
+
|
|
63
|
+
The masked `SCHEMA_DRIFT_TOKEN` CI variable is set on this project (id 74),
|
|
64
|
+
**not** Protected — same reasoning as Option A step 3 below.
|
|
65
|
+
|
|
66
|
+
**Proof pipelines, both directions, run before the flip:**
|
|
67
|
+
|
|
68
|
+
- **GREEN** — pipeline 8358 @ `dc9522dd` (branch
|
|
69
|
+
`proof/1175-schema-drift-green`): job `schema-drift-check` #84625 ran with
|
|
70
|
+
the token, cloned the baseline, and printed `RESULT: IN-SYNC (exit 0)`;
|
|
71
|
+
`pipeline-gate` succeeded.
|
|
72
|
+
- **RED** — pipelines 8355–8357 @ `bca78dae` (branch
|
|
73
|
+
`proof/1175-schema-drift-red`, a deliberately bogus enum value injected
|
|
74
|
+
into the vendored copy): `sync-vault-schema.mjs` reported drift, the job
|
|
75
|
+
failed with exit 1 — outside `allow_failure.exit_codes: [3]` — and
|
|
76
|
+
`pipeline-gate` never ran.
|
|
77
|
+
|
|
78
|
+
With both proofs recorded, `SCHEMA_DRIFT_OPTIONAL` is `"false"` at both
|
|
79
|
+
sites in `.gitlab-ci.yml` — `schema-drift-check` and `pipeline-gate`.
|
|
80
|
+
`tests/ci/schema-drift-check.test.mjs` pins the committed value on both
|
|
81
|
+
jobs, so a half-revert or a template refresh flipping one site back to
|
|
82
|
+
`"true"` fails the suite locally, not silently in a pipeline.
|
|
83
|
+
|
|
84
|
+
**Rotation / re-arm sequence** (token expiry or replacement):
|
|
85
|
+
|
|
86
|
+
0. **Re-mint the token.** Run the same `glab api --method POST … --input -`
|
|
87
|
+
recipe as Option A step 1, against the TARGET project (id 52), and copy
|
|
88
|
+
the response's `token` field immediately — it is shown exactly once.
|
|
89
|
+
1. `read -rs TOKEN` at the prompt (no echo), then pipe it into `glab variable
|
|
90
|
+
set` rather than passing it as a `--value` argument — a value passed on the
|
|
91
|
+
command line is visible to any other process on the host via `ps`, while
|
|
92
|
+
stdin is not:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
read -rs TOKEN
|
|
96
|
+
printf '%s' "$TOKEN" | glab variable set SCHEMA_DRIFT_TOKEN \
|
|
97
|
+
-R infrastructure/session-orchestrator --masked
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Not** `--protected`: `.gate-rules` (`.gitlab-ci.yml:74`) runs the job
|
|
101
|
+
on every branch and every MR pipeline, and a protected-only variable would
|
|
102
|
+
silently reproduce the exit-5 `UNAVAILABLE` failure on every unprotected
|
|
103
|
+
branch. (`glab variable set --help` documents stdin piping directly —
|
|
104
|
+
`cat file.txt | glab variable set SERVER_TOKEN` — but no `-`/dash value
|
|
105
|
+
for `--value`; the flag only accepts a literal string, so omitting it
|
|
106
|
+
entirely and piping the value is the only way to keep the token off argv.)
|
|
107
|
+
2. Push an ordinary commit and read the `schema-drift-check` job log for
|
|
108
|
+
`RESULT: IN-SYNC` — and confirm the job DURATION is well over 20 seconds
|
|
109
|
+
(see the pipeline-6815 warning above). A fast "success" is the exit-3
|
|
110
|
+
soft-skip in disguise, not a real run.
|
|
111
|
+
3. `SCHEMA_DRIFT_OPTIONAL` stays `"false"` at **both** sites —
|
|
112
|
+
`schema-drift-check` and `pipeline-gate`. A rotation replaces only the
|
|
113
|
+
credential, never the flag; if the flag was ever reverted for an
|
|
114
|
+
emergency, flip it back to `"false"` at both sites in one commit —
|
|
115
|
+
`tests/ci/schema-drift-check.test.mjs` pins the committed value on both
|
|
116
|
+
jobs, so a half-flip fails the suite locally.
|
|
117
|
+
4. Local counter-probe before trusting the pipeline: clone
|
|
118
|
+
`infrastructure/projects-baseline` with the token, make a throwaway copy of
|
|
119
|
+
`packages/zod-schemas/src/vault-frontmatter.ts` with one field
|
|
120
|
+
deliberately edited, then run
|
|
121
|
+
`node scripts/sync-vault-schema.mjs --check --canonical <path-to-edited-copy>`
|
|
122
|
+
— expect exit 1 with a diff naming the edited field. That confirms the
|
|
123
|
+
check diffs real content rather than passing on a broken comparison.
|
|
124
|
+
|
|
125
|
+
Per `.claude/rules/security.md` § SEC-005, this token's lifecycle belongs in
|
|
126
|
+
`.claude/docs/SECRETS-INVENTORY.md` once one exists — that file is not present
|
|
127
|
+
in this repo (measured 2026-09-02: no `.claude/docs/` directory tracked), so
|
|
128
|
+
the inventory is not adopted here and this section remains the sole record.
|
|
30
129
|
|
|
31
130
|
### Required CI variable
|
|
32
131
|
|
|
33
132
|
| Variable | Type | Mask | Protect | Value |
|
|
34
133
|
|---|---|---|---|---|
|
|
35
|
-
| `SCHEMA_DRIFT_TOKEN` | Variable | Yes |
|
|
134
|
+
| `SCHEMA_DRIFT_TOKEN` | Variable | Yes | No | Project Access Token or PAT — see Option A/B below |
|
|
36
135
|
|
|
37
136
|
If `SCHEMA_DRIFT_TOKEN` is **not set**, the job prints a `NOT VERIFIED` notice
|
|
38
137
|
and exits **3** — which `allow_failure.exit_codes` renders as an amber *warning*,
|
|
@@ -53,11 +152,12 @@ let alone diff a schema against it. Issue #933.
|
|
|
53
152
|
|
|
54
153
|
```yaml
|
|
55
154
|
variables:
|
|
56
|
-
SCHEMA_DRIFT_OPTIONAL: "
|
|
155
|
+
SCHEMA_DRIFT_OPTIONAL: "false"
|
|
57
156
|
```
|
|
58
157
|
|
|
59
|
-
It is the review-visible declaration that "no token" is *
|
|
60
|
-
state
|
|
158
|
+
It is the review-visible declaration that "no token" is *no longer* an
|
|
159
|
+
accepted state — armed 2026-09-03 (#1175, see § Activation status above).
|
|
160
|
+
The behaviour matrix:
|
|
61
161
|
|
|
62
162
|
| `SCHEMA_DRIFT_TOKEN` | `SCHEMA_DRIFT_OPTIONAL` | Exit | State | Pipeline effect |
|
|
63
163
|
|---|---|---|---|---|
|
|
@@ -76,14 +176,53 @@ a schema diff that does not exist. Only 3 is listed in
|
|
|
76
176
|
outcome also prints its own `[schema-drift] RESULT: <STATE>` line, so the job log
|
|
77
177
|
answers "what happened" without the reader having to know this table.
|
|
78
178
|
|
|
79
|
-
**
|
|
80
|
-
`
|
|
179
|
+
**Caveat — a second, narrower exit-3 collision (do not change the YAML for
|
|
180
|
+
it).** `scripts/sync-vault-schema.mjs` has its own exit 3, for a different
|
|
181
|
+
condition: malformed sentinel comments in `validator.mjs` (only one of
|
|
182
|
+
`begin`/`end` present). If `--check` ever hit that branch, it would return
|
|
183
|
+
exit 3 from the tool itself — and `allow_failure.exit_codes: [3]` reads the
|
|
184
|
+
shell's final exit code, not which tool produced it, so a genuine tooling
|
|
185
|
+
defect (broken sentinels) would render as the same amber "no token, declared
|
|
186
|
+
optional" warning that the missing-token guard produces. This is a caveat to
|
|
187
|
+
note, not a blocker: the sentinels are intact today, and the fix — if it is
|
|
188
|
+
ever needed — is giving `sync-vault-schema.mjs`'s malformed-sentinel case a
|
|
189
|
+
distinct exit code, not a change here.
|
|
190
|
+
|
|
191
|
+
**This is what the armed state looks like.** `SCHEMA_DRIFT_OPTIONAL` is
|
|
192
|
+
`"false"` in `.gitlab-ci.yml` at **both** places: the `schema-drift-check`
|
|
81
193
|
job and `pipeline-gate`. One flag, two enforcement points;
|
|
82
|
-
`tests/ci/schema-drift-check.test.mjs` asserts the mirroring
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
194
|
+
`tests/ci/schema-drift-check.test.mjs` asserts the mirroring AND pins the
|
|
195
|
+
literal `"false"` value on both jobs, so a half-flip — or a full revert —
|
|
196
|
+
fails the suite locally rather than silently leaving one point advisory. A
|
|
197
|
+
missing or expired token now hard-fails the pipeline (exit 4) instead of the
|
|
198
|
+
tolerated amber warning — that is the whole point of the flag: the opt-out is
|
|
199
|
+
a line in a reviewed file, not the accidental side effect of an unset CI
|
|
200
|
+
variable.
|
|
201
|
+
|
|
202
|
+
**To switch it back to amber temporarily** (a token rotation window, or
|
|
203
|
+
taking the check offline for an emergency): set `SCHEMA_DRIFT_OPTIONAL` to
|
|
204
|
+
`"true"` at **both** sites, in one commit — the same mirrored-pair discipline
|
|
205
|
+
applies in reverse, and the same test catches a half-revert. Re-arm by
|
|
206
|
+
flipping both sites back to `"false"` once the reason for the amber window is
|
|
207
|
+
resolved; see § Rotation / re-arm sequence above for the token side of that
|
|
208
|
+
operation.
|
|
209
|
+
|
|
210
|
+
**Fork / external-contributor MR caveat.** `.gate-rules` (`.gitlab-ci.yml:74`)
|
|
211
|
+
includes `if: $CI_PIPELINE_SOURCE == "merge_request_event"`, so a merge
|
|
212
|
+
request pipeline runs `schema-drift-check` regardless of who opened it — but
|
|
213
|
+
GitLab does not pass the target project's masked CI/CD variables to a
|
|
214
|
+
pipeline running a **forked** project's code, by design, so that an untrusted
|
|
215
|
+
fork cannot exfiltrate a secret. A fork/contributor MR therefore cannot read
|
|
216
|
+
`SCHEMA_DRIFT_TOKEN` even though the variable is set and unprotected on this
|
|
217
|
+
project, and with `SCHEMA_DRIFT_OPTIONAL: "false"` that reads as a genuinely
|
|
218
|
+
missing token: exit **4** (`MISCONFIGURED`), a hard pipeline failure — not the
|
|
219
|
+
amber `SKIPPED` a same-project branch would get. The accepted mitigation is
|
|
220
|
+
either of: a maintainer re-runs the pipeline from within this project (e.g.
|
|
221
|
+
pushing the same commit to a branch here, where the variable IS available),
|
|
222
|
+
or a maintainer temporarily sets `SCHEMA_DRIFT_OPTIONAL: "true"` on that one
|
|
223
|
+
MR/branch for the duration of review. Do not weaken the committed default in
|
|
224
|
+
`.gitlab-ci.yml` for this — it stays `"false"` at both sites per the armed
|
|
225
|
+
state above.
|
|
87
226
|
|
|
88
227
|
> **Before you flip it, run ONE pipeline with the token present while
|
|
89
228
|
> `SCHEMA_DRIFT_OPTIONAL` is still `"true"`, and check the job's DURATION.**
|
|
@@ -98,35 +237,93 @@ not the accidental side effect of an unset CI variable.
|
|
|
98
237
|
> exactly this failure — pipeline 6815 reported SUCCESS in 17 s having checked
|
|
99
238
|
> nothing (issue #933).
|
|
100
239
|
|
|
101
|
-
### Option A —
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
240
|
+
### Option A — Project Access Token (recommended — works with the current clone URL)
|
|
241
|
+
|
|
242
|
+
GitLab resolves a **deploy token** by its own fixed username
|
|
243
|
+
(`gitlab+deploy-token-<n>`, or a custom username if one was set at creation).
|
|
244
|
+
The job's clone step hardcodes the login as `oauth2:${SCHEMA_DRIFT_TOKEN}`
|
|
245
|
+
(`.gitlab-ci.yml` ~:652) — `oauth2` is the username GitLab expects for a
|
|
246
|
+
Personal or Project Access Token, not for a deploy token. A deploy token's
|
|
247
|
+
value paired with that hardcoded username fails authentication at clone time
|
|
248
|
+
and surfaces as exit 5 `UNAVAILABLE`, which reads as a network/credential
|
|
249
|
+
problem rather than "wrong username" (see the demoted Deploy Token option
|
|
250
|
+
below). Tokens with **PAT semantics** — GitLab accepts any username alongside
|
|
251
|
+
the token value — authenticate correctly with this clone URL: a Personal
|
|
252
|
+
Access Token, or, least-privilege, a **Project Access Token** scoped to the
|
|
253
|
+
TARGET project (`infrastructure/projects-baseline`). A Project Access Token
|
|
254
|
+
is preferred over a personal PAT for the same reason the deploy token used to
|
|
255
|
+
be recommended: it belongs to the project, not a person, and survives staff
|
|
256
|
+
changes.
|
|
257
|
+
|
|
258
|
+
1. Create the token via API against the TARGET project (id 52) — GitLab has
|
|
259
|
+
no path to create a Project Access Token FOR a project from outside that
|
|
260
|
+
project's own Settings UI, so use `glab api`:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
glab api --hostname "$GITLAB_HOST" -X POST "projects/52/access_tokens" \
|
|
264
|
+
-H 'Content-Type: application/json' --input - <<'JSON'
|
|
265
|
+
{"name":"session-orchestrator-ci-schema-drift","scopes":["read_repository"],"access_level":20,"expires_at":"2027-09-01"}
|
|
266
|
+
JSON
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
`--input -` plus the explicit `Content-Type: application/json` header is
|
|
270
|
+
required because the payload has a nested type (`scopes` is a JSON array),
|
|
271
|
+
which `glab api`'s `-f`/`-F` flag form cannot express. `access_level: 20`
|
|
272
|
+
is Reporter — the lowest access level that can read repository content.
|
|
273
|
+
`expires_at` is an operator choice, not a fixed value; the token created
|
|
274
|
+
for this document's own dry run (2026-09-02) was set 1 year out
|
|
275
|
+
(`2027-09-01`) — rotate before expiry.
|
|
276
|
+
|
|
277
|
+
2. The response's `token` field holds the token value and is **shown exactly
|
|
278
|
+
once** — copy it immediately; GitLab will not display it again.
|
|
279
|
+
|
|
280
|
+
3. Store it in `session-orchestrator` CI/CD variables as `SCHEMA_DRIFT_TOKEN`.
|
|
281
|
+
Prefer stdin over `--value` — a value passed as a command-line argument is
|
|
282
|
+
visible to other processes on the host (`ps`), while stdin is not:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
read -rs TOKEN
|
|
286
|
+
printf '%s' "$TOKEN" | glab variable set SCHEMA_DRIFT_TOKEN \
|
|
287
|
+
-R infrastructure/session-orchestrator --masked
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Masked:** Yes. **Not** `--protected` — `.gate-rules` (`.gitlab-ci.yml:74`)
|
|
291
|
+
runs the job on every branch and every MR pipeline, so a protected-only
|
|
292
|
+
variable would silently be absent everywhere the job actually needs it.
|
|
118
293
|
|
|
119
294
|
### Option B — Personal Access Token (fallback)
|
|
120
295
|
|
|
121
|
-
|
|
296
|
+
The same PAT-semantics reasoning from Option A applies: a personal PAT
|
|
297
|
+
authenticates under any username, so it works with the hardcoded `oauth2:`
|
|
298
|
+
clone login. Use this only if you cannot create a Project Access Token on
|
|
299
|
+
`infrastructure/projects-baseline` (e.g. you lack Owner/Maintainer there).
|
|
122
300
|
|
|
123
301
|
1. Go to your GitLab profile → **Access Tokens**.
|
|
124
302
|
2. Create a token with scope `read_repository` and a reasonable expiry.
|
|
125
303
|
3. Store it in `session-orchestrator` CI/CD variables as `SCHEMA_DRIFT_TOKEN`
|
|
126
|
-
(Masked: Yes
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
the CI credential survives staff changes.
|
|
304
|
+
(Masked: Yes, **not** Protected — see Option A step 3 above).
|
|
305
|
+
|
|
306
|
+
A personal PAT is tied to the creating user's account and access; prefer the
|
|
307
|
+
Project Access Token in Option A so the CI credential survives staff changes.
|
|
308
|
+
|
|
309
|
+
### Deploy Token — does not work with the current clone URL
|
|
310
|
+
|
|
311
|
+
This was the previously recommended option; it is demoted here because, as
|
|
312
|
+
the job is written today, it does not authenticate. GitLab deploy tokens
|
|
313
|
+
authenticate under their OWN username (`gitlab+deploy-token-<n>`, or a custom
|
|
314
|
+
username set at creation) — never as `oauth2`. The job's clone step hardcodes
|
|
315
|
+
`oauth2:${SCHEMA_DRIFT_TOKEN}` (`.gitlab-ci.yml` ~:652), so a deploy token's
|
|
316
|
+
value paired with the wrong username fails authentication at clone time. This
|
|
317
|
+
job reports that as exit 5 `UNAVAILABLE` — read as a network/credential-scope
|
|
318
|
+
problem, when the actual cause is the username mismatch.
|
|
319
|
+
|
|
320
|
+
To use a deploy token instead of Option A, `.gitlab-ci.yml`'s clone step would
|
|
321
|
+
need to stop hardcoding `oauth2` — either read the deploy token's own username
|
|
322
|
+
from a second CI variable and interpolate it into the clone URL, or create the
|
|
323
|
+
deploy token with a custom username of `oauth2` if the GitLab instance allows
|
|
324
|
+
choosing one. Neither change is made in this repo; that edit is out of this
|
|
325
|
+
document's scope. Option A avoids needing it at all, by using a token whose
|
|
326
|
+
username requirement (any username) already matches the hardcoded login.
|
|
130
327
|
|
|
131
328
|
### Verification path
|
|
132
329
|
|
|
@@ -162,8 +359,12 @@ Documenting it here for completeness:
|
|
|
162
359
|
`infrastructure/session-orchestrator`.
|
|
163
360
|
- Once the allowlist entry is saved, the job can use `CI_JOB_TOKEN` directly
|
|
164
361
|
and `SCHEMA_DRIFT_TOKEN` is not needed.
|
|
165
|
-
- Issue #279 chose the
|
|
166
|
-
in the foreign project and works immediately after
|
|
362
|
+
- Issue #279 chose the token-variable path over this allowlist because it
|
|
363
|
+
requires no admin action in the foreign project and works immediately after
|
|
364
|
+
variable creation. The original choice was a deploy token; as documented in
|
|
365
|
+
Option A above, a deploy token does not actually authenticate with this
|
|
366
|
+
job's hardcoded `oauth2:` clone login, so a Project Access Token (or PAT)
|
|
367
|
+
is the variant that delivers on that original reasoning.
|
|
167
368
|
|
|
168
369
|
## `pipeline-gate` — the fan-in job
|
|
169
370
|
|