session-orchestrator 3.21.0 → 3.23.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/commands/autopilot-multi.md +14 -0
- package/.cursor/commands/autopilot.md +14 -0
- package/.cursor/commands/bootstrap.md +14 -0
- package/.cursor/commands/brainstorm.md +14 -0
- package/.cursor/commands/close.md +13 -0
- package/.cursor/commands/contract-version-bump.md +14 -0
- package/.cursor/commands/debug.md +14 -0
- package/.cursor/commands/discovery.md +14 -0
- package/.cursor/commands/dispatcher.md +14 -0
- package/.cursor/commands/eli5.md +14 -0
- package/.cursor/commands/eval.md +14 -0
- package/.cursor/commands/evolve.md +14 -0
- package/.cursor/commands/go.md +14 -0
- package/.cursor/commands/grill.md +14 -0
- package/.cursor/commands/harness-audit.md +13 -0
- package/.cursor/commands/journey-audit.md +14 -0
- package/.cursor/commands/memory-cleanup.md +14 -0
- package/.cursor/commands/persona-panel.md +14 -0
- package/.cursor/commands/plan.md +14 -0
- package/.cursor/commands/portfolio.md +14 -0
- package/.cursor/commands/reconcile.md +14 -0
- package/.cursor/commands/release.md +14 -0
- package/.cursor/commands/repo-audit.md +13 -0
- package/.cursor/commands/session.md +14 -0
- package/.cursor/commands/spinout.md +14 -0
- package/.cursor/commands/sunset-review.md +14 -0
- package/.cursor/commands/templates-ack.md +14 -0
- package/.cursor/commands/test.md +14 -0
- package/.cursor/hooks.json +60 -0
- package/.cursor/rules/000-session-orchestrator.mdc +11 -2
- package/.cursor/rules/010-session-workflow.mdc +9 -1
- package/.cursor/rules/020-quality-gates.mdc +1 -1
- package/.cursor/rules/030-wave-execution.mdc +1 -1
- package/.cursor/rules/040-discovery.mdc +6 -6
- package/.cursor/rules/050-plan.mdc +10 -10
- package/.cursor/rules/070-gitlab-ops.mdc +73 -57
- package/.cursor/rules/080-ecosystem-health.mdc +7 -7
- package/.cursor/skills/architecture/SKILL.md +13 -0
- package/.cursor/skills/autopilot/SKILL.md +12 -0
- package/.cursor/skills/bootstrap/SKILL.md +12 -0
- package/.cursor/skills/brainstorm/SKILL.md +13 -0
- package/.cursor/skills/claude-md-drift-check/SKILL.md +13 -0
- package/.cursor/skills/contract-version-bump/SKILL.md +12 -0
- package/.cursor/skills/convergence-monitoring/SKILL.md +12 -0
- package/.cursor/skills/daily/SKILL.md +12 -0
- package/.cursor/skills/debug/SKILL.md +13 -0
- package/.cursor/skills/discovery/SKILL.md +13 -0
- package/.cursor/skills/dispatcher/SKILL.md +13 -0
- package/.cursor/skills/docs-orchestrator/SKILL.md +13 -0
- package/.cursor/skills/domain-model/SKILL.md +13 -0
- package/.cursor/skills/ecosystem-health/SKILL.md +13 -0
- package/.cursor/skills/eli5/SKILL.md +13 -0
- package/.cursor/skills/eval/SKILL.md +12 -0
- package/.cursor/skills/evolve/SKILL.md +13 -0
- package/.cursor/skills/frontmatter-guard/SKILL.md +13 -0
- package/.cursor/skills/gitlab-ops/SKILL.md +13 -0
- package/.cursor/skills/gitlab-portfolio/SKILL.md +13 -0
- package/.cursor/skills/grill/SKILL.md +13 -0
- package/.cursor/skills/hook-development/SKILL.md +13 -0
- package/.cursor/skills/journey-audit/SKILL.md +13 -0
- package/.cursor/skills/mcp-builder/SKILL.md +13 -0
- package/.cursor/skills/memory-cleanup/SKILL.md +12 -0
- package/.cursor/skills/mode-selector/SKILL.md +13 -0
- package/.cursor/skills/npm-publish/SKILL.md +12 -0
- package/.cursor/skills/peekaboo-driver/SKILL.md +13 -0
- package/.cursor/skills/persona-panel/SKILL.md +12 -0
- package/.cursor/skills/plan/SKILL.md +13 -0
- package/.cursor/skills/playwright-driver/SKILL.md +13 -0
- package/.cursor/skills/quality-gates/SKILL.md +13 -0
- package/.cursor/skills/reconcile/SKILL.md +12 -0
- package/.cursor/skills/repo-audit/SKILL.md +13 -0
- package/.cursor/skills/session-end/SKILL.md +13 -0
- package/.cursor/skills/session-plan/SKILL.md +13 -0
- package/.cursor/skills/session-start/SKILL.md +13 -0
- package/.cursor/skills/skill-creator/SKILL.md +13 -0
- package/.cursor/skills/spinout/SKILL.md +12 -0
- package/.cursor/skills/sunset-review/SKILL.md +13 -0
- package/.cursor/skills/test-runner/SKILL.md +13 -0
- package/.cursor/skills/tmux-layout/SKILL.md +13 -0
- package/.cursor/skills/ubiquitous-language/SKILL.md +13 -0
- package/.cursor/skills/using-orchestrator/SKILL.md +13 -0
- package/.cursor/skills/vault-mirror/SKILL.md +13 -0
- package/.cursor/skills/vault-sync/SKILL.md +13 -0
- package/.cursor/skills/wave-executor/SKILL.md +13 -0
- package/.cursor/skills/write-executable-plan/SKILL.md +13 -0
- package/.mcp.json +4 -1
- package/CHANGELOG.md +269 -0
- package/README.md +18 -15
- package/agents/AGENTS.md +23 -4
- package/agents/code-implementer.md +2 -1
- package/agents/db-specialist.md +2 -1
- package/agents/docs-writer.md +3 -1
- package/agents/eval-judge.md +1 -1
- package/agents/memory-proposal-collector.md +6 -4
- package/agents/session-reviewer.md +7 -1
- package/agents/test-writer.md +2 -1
- package/agents/ui-developer.md +2 -1
- package/commands/bootstrap.md +2 -2
- package/commands/close.md +3 -1
- package/commands/eli5.md +33 -0
- package/commands/go.md +1 -1
- package/commands/journey-audit.md +43 -0
- package/commands/release.md +5 -3
- package/commands/test.md +2 -2
- package/docs/USER-GUIDE.md +2 -2
- package/docs/ci-setup.md +14 -0
- package/docs/codex-setup.md +64 -0
- package/docs/components.md +7 -6
- package/docs/cursor-setup.md +26 -47
- package/docs/events-schema.md +76 -4
- package/docs/github-mirror-protection.md +197 -0
- package/docs/pi-setup.md +2 -0
- package/docs/rule-authoring.md +3 -1
- package/docs/scope-collision-guard.md +52 -5
- package/docs/session-config-reference.md +57 -12
- package/docs/session-config-template.md +4 -3
- package/docs/telemetry.md +22 -0
- package/hooks/_lib/lock-bootstrap.mjs +26 -16
- package/hooks/_lib/vcs-create-matcher.mjs +397 -38
- package/hooks/enforce-scope.mjs +64 -0
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +201 -20
- package/hooks/hooks-pi.json +1 -1
- package/hooks/hooks.json +12 -2
- package/hooks/on-session-end.mjs +237 -104
- package/hooks/on-session-start.mjs +404 -110
- package/hooks/on-stop.mjs +48 -9
- package/hooks/post-subagent-discovery-validator.mjs +34 -3
- package/hooks/post-tool-batch-wave-signal.mjs +11 -2
- package/hooks/pre-auq-clarity.mjs +787 -0
- package/hooks/pre-bash-issue-budget.mjs +133 -21
- package/hooks/pre-bash-sessions-ledger-guard.mjs +159 -0
- package/hooks/pre-bash-staging-fence.mjs +4 -0
- package/hooks/pre-task-scope-disjoint.mjs +368 -35
- package/hooks/skill-invocation-telemetry.mjs +21 -10
- package/monitors/monitors.json +6 -0
- package/package.json +3 -1
- package/pi/prompts/eli5.md +12 -0
- package/pi/prompts/journey-audit.md +12 -0
- package/rules/_index.md +9 -1
- package/rules/always-on/ask-via-tool.md +62 -0
- package/rules/always-on/bash-harness-pitfalls.md +168 -0
- package/rules/always-on/build-value.md +47 -0
- package/rules/always-on/cross-session-messaging.md +59 -0
- package/rules/always-on/loop-and-monitor.md +221 -0
- package/rules/always-on/parallel-sessions.md +142 -12
- package/rules/always-on/receiving-review.md +108 -0
- package/rules/always-on/test-value.md +40 -0
- package/rules/always-on/verification-before-completion.md +77 -0
- package/scripts/archive-closed-prds.mjs +258 -18
- package/scripts/auq-audit.mjs +825 -0
- package/scripts/autopilot.mjs +12 -8
- package/scripts/backfill-evidence-digest.mjs +376 -0
- package/scripts/cursor-install.mjs +89 -48
- package/scripts/export-hw-learnings.mjs +143 -2
- package/scripts/express-path.mjs +299 -0
- package/scripts/generate-cursor-adapter.mjs +253 -0
- package/scripts/github-protection-audit.mjs +358 -0
- package/scripts/lib/auq/clarity.mjs +1314 -0
- package/scripts/lib/auq/parse.mjs +1006 -0
- package/scripts/lib/auq/schema.mjs +1457 -0
- package/scripts/lib/autopilot/worktree-pipeline.mjs +240 -16
- package/scripts/lib/build-live-signals.mjs +24 -5
- package/scripts/lib/ci-status-banner.mjs +221 -68
- package/scripts/lib/command-blocker.mjs +70 -0
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +32 -9
- package/scripts/lib/config/reconcile.mjs +79 -4
- package/scripts/lib/config/section-extractor.mjs +235 -36
- package/scripts/lib/config/vault-integration.mjs +12 -1
- package/scripts/lib/config-schema.mjs +9 -1
- package/scripts/lib/config.mjs +57 -6
- package/scripts/lib/convergence-monitor.mjs +13 -2
- package/scripts/lib/cursor-hook-bridge.mjs +443 -0
- package/scripts/lib/dispatcher/cli.mjs +2 -2
- package/scripts/lib/dispatcher/rank.mjs +4 -7
- package/scripts/lib/express-path.mjs +327 -0
- package/scripts/lib/file-lock.mjs +22 -4
- package/scripts/lib/gates/gate-full.mjs +84 -11
- package/scripts/lib/gates/gate-helpers.mjs +93 -21
- package/scripts/lib/git-config-drift.mjs +134 -5
- package/scripts/lib/host-identity.mjs +247 -2
- package/scripts/lib/instruction-budget-guard.mjs +31 -1
- package/scripts/lib/io.mjs +239 -0
- package/scripts/lib/issue-budget.mjs +284 -31
- package/scripts/lib/learnings/io.mjs +55 -10
- package/scripts/lib/learnings/schema.mjs +95 -28
- package/scripts/lib/lock-reaper.mjs +7 -1
- package/scripts/lib/locks/staging-fence-lock.mjs +5 -1
- package/scripts/lib/locks/state-md-lock.mjs +8 -1
- package/scripts/lib/memory-banner.mjs +5 -2
- package/scripts/lib/memory-paths.mjs +15 -6
- package/scripts/lib/mode-selector/scoring.mjs +53 -6
- package/scripts/lib/owner-interview.mjs +78 -32
- package/scripts/lib/peer-discovery.mjs +73 -22
- package/scripts/lib/platform.mjs +72 -9
- package/scripts/lib/plugin-root.mjs +143 -19
- package/scripts/lib/project-hygiene.mjs +104 -4
- package/scripts/lib/quality-gate.mjs +271 -13
- package/scripts/lib/reconcile/emitter.mjs +87 -19
- package/scripts/lib/reconcile/engine.mjs +281 -13
- package/scripts/lib/reconcile/idempotency.mjs +102 -1
- package/scripts/lib/reconcile/renderer.mjs +165 -7
- package/scripts/lib/reconcile/sanitize.mjs +40 -17
- package/scripts/lib/reconcile/writer.mjs +415 -84
- package/scripts/lib/resource-probe/evaluate.mjs +330 -149
- package/scripts/lib/resource-probe/probe-platform.mjs +35 -0
- package/scripts/lib/resource-probe.mjs +18 -2
- package/scripts/lib/rule-loader.mjs +37 -2
- package/scripts/lib/rules-sync.mjs +51 -8
- package/scripts/lib/scope-gate.mjs +90 -0
- package/scripts/lib/session-close-backfill.mjs +369 -28
- package/scripts/lib/session-discovery.mjs +13 -3
- package/scripts/lib/session-end/phase-skip.mjs +37 -4
- package/scripts/lib/session-end/worktree-cleanup.mjs +154 -7
- package/scripts/lib/session-id.mjs +30 -14
- package/scripts/lib/session-identity/own-session.mjs +159 -0
- package/scripts/lib/session-lock.mjs +85 -30
- package/scripts/lib/session-schema/normalizer.mjs +70 -3
- package/scripts/lib/session-schema/validator.mjs +40 -0
- package/scripts/lib/session-start-probes.mjs +608 -0
- package/scripts/lib/session-transition.mjs +277 -0
- package/scripts/lib/sessions-staleness-banner.mjs +124 -57
- package/scripts/lib/spiral-carryover.mjs +111 -9
- package/scripts/lib/state-md/frontmatter-mutators.mjs +41 -8
- package/scripts/lib/state-md/mission-status.mjs +467 -72
- package/scripts/lib/state-md/yaml-parser.mjs +145 -16
- package/scripts/lib/state-md.mjs +12 -2
- package/scripts/lib/telemetry/sync.mjs +46 -8
- package/scripts/lib/validate/check-agents.mjs +66 -0
- package/scripts/lib/validate/check-auq-clarity.mjs +274 -0
- package/scripts/lib/validate/check-cursor-adapter.mjs +102 -0
- package/scripts/lib/validate/check-dead-bridge.mjs +24 -2
- package/scripts/lib/validate/check-doc-cli-commands.mjs +16 -32
- package/scripts/lib/validate/check-hooks-symmetry.mjs +59 -63
- package/scripts/lib/validate/check-playwright-mcp-canary.mjs +13 -22
- package/scripts/lib/validate/check-plugin-monitors.mjs +10 -4
- package/scripts/lib/validate/check-rules.mjs +153 -9
- package/scripts/lib/validate/check-test-value-bans.mjs +165 -17
- package/scripts/lib/validate/check-unwired-features.mjs +340 -32
- package/scripts/lib/validate/repo-files.mjs +275 -0
- package/scripts/lib/validate-vendored-rules.mjs +229 -7
- package/scripts/lib/vault-backfill/glab.mjs +91 -58
- package/scripts/lib/vault-backfill/manifest.mjs +28 -8
- package/scripts/lib/vault-mirror/process.mjs +99 -43
- package/scripts/lib/vault-mirror/telemetry.mjs +210 -0
- package/scripts/lib/vault-staleness-banner.mjs +76 -6
- package/scripts/lib/vault-status/board-writer.mjs +211 -10
- package/scripts/lib/vault-status/narrative-mirror.mjs +188 -8
- package/scripts/lib/vcs-repo-spec.mjs +182 -13
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +832 -0
- package/scripts/lib/wave-resource-gate.mjs +67 -73
- package/scripts/lib/wave-transcript-tail.mjs +869 -0
- package/scripts/materialize-wave-scope.mjs +478 -0
- package/scripts/mcp-server.sh +11 -2
- package/scripts/parse-config.mjs +65 -0
- package/scripts/release.mjs +443 -122
- package/scripts/run-quality-gate.mjs +14 -0
- package/scripts/token-audit.sh +9 -2
- package/scripts/validate-plugin.mjs +6 -0
- package/scripts/validate-wave-scope.mjs +73 -1
- package/scripts/vault-backfill.mjs +32 -5
- package/scripts/vault-mirror.mjs +203 -34
- package/skills/_shared/monitor-patterns.md +31 -5
- package/skills/_shared/parallel-aware-auq.md +31 -25
- package/skills/_shared/parallel-aware-preamble.md +35 -4
- package/skills/_shared/platform-tools.md +11 -5
- package/skills/_shared/state-ownership.md +61 -8
- package/skills/autopilot/SKILL.md +5 -1
- package/skills/bootstrap/SKILL.md +5 -4
- package/skills/bootstrap/_shared-template.md +18 -10
- package/skills/bootstrap/deep-template.md +10 -6
- package/skills/bootstrap/fast-template.md +15 -8
- package/skills/bootstrap/standard-template.md +10 -6
- package/skills/brainstorm/SKILL.md +18 -18
- package/skills/brainstorm/soul.md +12 -0
- package/skills/claude-md-drift-check/checker.mjs +39 -11
- package/skills/discovery/SKILL.md +28 -24
- package/skills/dispatcher/SKILL.md +1 -1
- package/skills/eli5/SKILL.md +43 -0
- package/skills/evolve/SKILL.md +8 -9
- package/skills/gitlab-ops/SKILL.md +30 -26
- package/skills/grill/SKILL.md +6 -6
- package/skills/grill/soul.md +16 -0
- package/skills/journey-audit/SKILL.md +269 -0
- package/skills/memory-cleanup/SKILL.md +2 -2
- package/skills/npm-publish/SKILL.md +4 -4
- package/skills/peekaboo-driver/SKILL.md +18 -6
- package/skills/persona-panel/SKILL.md +1 -1
- package/skills/plan/SKILL.md +18 -16
- package/skills/plan/mode-feature.md +1 -1
- package/skills/plan/mode-new.md +35 -23
- package/skills/plan/soul.md +12 -0
- package/skills/reconcile/SKILL.md +44 -4
- package/skills/session-end/SKILL.md +70 -24
- package/skills/session-end/metrics-collection.md +7 -4
- package/skills/session-end/phase-3-6-tail.md +48 -5
- package/skills/session-end/phase-3-7a-recommendations.md +16 -2
- package/skills/session-plan/SKILL.md +6 -1
- package/skills/session-plan/wave-template.md +1 -0
- package/skills/session-start/SKILL.md +96 -48
- package/skills/session-start/phase-2-5-docs-planning.md +8 -8
- package/skills/session-start/phase-4-5-resource-health.md +82 -19
- package/skills/session-start/phase-7-5-mode-selector.md +15 -3
- package/skills/session-start/phase-8-5-express-path.md +77 -12
- package/skills/session-start/soul.md +110 -0
- package/skills/test-runner/SKILL.md +2 -2
- package/skills/using-orchestrator/SKILL.md +1 -1
- package/skills/vault-sync/validator.mjs +31 -0
- package/skills/wave-executor/SKILL.md +4 -2
- package/skills/wave-executor/circuit-breaker.md +34 -9
- package/skills/wave-executor/wave-loop.md +129 -24
- package/skills/write-executable-plan/SKILL.md +6 -6
- package/templates/_shared/journey-manifest.md +110 -0
- package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +0 -8
- package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +0 -8
- package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +0 -8
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +0 -8
- package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +0 -8
- package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +0 -8
- package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +0 -10
- package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +0 -8
- package/skills/vault-sync/tests/fixtures/clean-vault/README.md +0 -3
- package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +0 -11
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +0 -9
- package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +0 -8
- package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +0 -7
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +0 -9
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +0 -11
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +0 -3
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +0 -3
- package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +0 -11
- package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
- package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +0 -11
- package/skills/vault-sync/tests/schema-drift.test.mjs +0 -133
- package/templates/_shared/rules/parallel-sessions.md +0 -77
|
@@ -48,12 +48,12 @@ Run a single AUQ to let the user characterize the problem in their own words:
|
|
|
48
48
|
```
|
|
49
49
|
AskUserQuestion({
|
|
50
50
|
questions: [{
|
|
51
|
-
question: "
|
|
52
|
-
header: "
|
|
51
|
+
question: "What do you want to brainstorm, and what is still unclear about it?",
|
|
52
|
+
header: "Frame",
|
|
53
53
|
options: [
|
|
54
|
-
{ label: "
|
|
55
|
-
{ label: "Scope / boundaries
|
|
56
|
-
{ label: "
|
|
54
|
+
{ label: "The user-facing surface", description: "You know what to build but not how it should work for the user." },
|
|
55
|
+
{ label: "Scope / boundaries", description: "You're not sure how much to build, or where one feature ends and another begins." },
|
|
56
|
+
{ label: "Several approaches — pick one", description: "You see 2-3 ways to solve this and aren't sure which is best." },
|
|
57
57
|
{ label: "Other / describe below", description: "Free-form: describe the ambiguity in the next prompt." }
|
|
58
58
|
],
|
|
59
59
|
multiSelect: false
|
|
@@ -98,9 +98,9 @@ Example round (adapt to the actual feature):
|
|
|
98
98
|
AskUserQuestion({
|
|
99
99
|
questions: [{
|
|
100
100
|
question: "Who is the primary user of this feature, and how do they trigger it?",
|
|
101
|
-
header: "User
|
|
101
|
+
header: "User surface",
|
|
102
102
|
options: [
|
|
103
|
-
{ label: "
|
|
103
|
+
{ label: "Signed-in user, UI action (Recommended)", description: "Pro: fits existing session model. Con: requires UI component work." },
|
|
104
104
|
{ label: "Automated trigger (webhook, cron, event)", description: "Pro: no manual user step. Con: harder to debug and test." },
|
|
105
105
|
{ label: "Admin-only operation", description: "Pro: simpler access control. Con: limits who can self-serve." },
|
|
106
106
|
{ label: "Other / describe below", description: "Describe the trigger mechanism." }
|
|
@@ -128,12 +128,12 @@ Once the dialogue has enough signal, synthesize 2-3 concrete implementation appr
|
|
|
128
128
|
```
|
|
129
129
|
AskUserQuestion({
|
|
130
130
|
questions: [{
|
|
131
|
-
question: "
|
|
132
|
-
header: "
|
|
131
|
+
question: "Which of these approaches fits best?",
|
|
132
|
+
header: "Approach",
|
|
133
133
|
options: [
|
|
134
|
-
{ label: "
|
|
135
|
-
{ label: "
|
|
136
|
-
{ label: "
|
|
134
|
+
{ label: "A — [short summary] (Recommended)", description: "Best balance of value, reversibility and scope, because [key pro]. Cost: [key con]. Complexity: low/medium/high." },
|
|
135
|
+
{ label: "B — [short summary]", description: "Trade-offs: [key pro]. Cost: [key con]. Complexity: low/medium/high." },
|
|
136
|
+
{ label: "C — [short summary]", description: "Trade-offs: [key pro]. Cost: [key con]. Complexity: low/medium/high." }
|
|
137
137
|
],
|
|
138
138
|
multiSelect: false
|
|
139
139
|
}]
|
|
@@ -231,13 +231,13 @@ Present the spec path and summary to the user. Then ask via AUQ:
|
|
|
231
231
|
```
|
|
232
232
|
AskUserQuestion({
|
|
233
233
|
questions: [{
|
|
234
|
-
question: "The
|
|
235
|
-
header: "
|
|
234
|
+
question: "The spec is at docs/specs/YYYY-MM-DD-<slug>-design.md. How do you want to proceed?",
|
|
235
|
+
header: "Hand-off",
|
|
236
236
|
options: [
|
|
237
|
-
{ label: "Proceed to /plan feature (Recommended)", description: "
|
|
238
|
-
{ label: "Proceed to /write-executable-plan", description: "
|
|
239
|
-
{ label: "Revise the spec", description: "
|
|
240
|
-
{ label: "Done for now", description: "
|
|
237
|
+
{ label: "Proceed to /plan feature (Recommended)", description: "Turns the spec into a PRD with acceptance criteria, then files the issues. Cost: one more question round." },
|
|
238
|
+
{ label: "Proceed to /write-executable-plan", description: "Skips the formal PRD and writes a step-by-step executable plan instead — tracked in #39 (a numbered ticket, not yet released)." },
|
|
239
|
+
{ label: "Revise the spec", description: "Describe what to change; the spec is updated and comes back here." },
|
|
240
|
+
{ label: "Done for now", description: "The spec stays on disk as a reference. Nothing else runs." }
|
|
241
241
|
],
|
|
242
242
|
multiSelect: false
|
|
243
243
|
}]
|
|
@@ -62,6 +62,18 @@ The active level is `efficiency.output-level` in `~/.config/session-orchestrator
|
|
|
62
62
|
- Shape: explain WHY each option is on the table, name the paths you already discarded and why, define unfamiliar terms on first use.
|
|
63
63
|
- Escalation: `expand <topic>` — see § Escalation above.
|
|
64
64
|
|
|
65
|
+
### Register — how a sentence reads
|
|
66
|
+
|
|
67
|
+
The budgets above set *how much* you say; the register sets *how*. It is
|
|
68
|
+
defined once, in `skills/session-start/soul.md` § "Register — how a sentence
|
|
69
|
+
reads", and binds here unchanged: the frame ("write for someone who knows this
|
|
70
|
+
project but has not seen what you just saw"), the plain-words test with its
|
|
71
|
+
five worked cases, and its precedence over § "Never traded for brevity" above.
|
|
72
|
+
Read it there. It is not repeated here on purpose — the § Output Levels intro
|
|
73
|
+
sentence already exists in four copies across the four souls with nothing
|
|
74
|
+
checking their parity, and a fifth copied rule would drift the same way. A
|
|
75
|
+
pointer cannot.
|
|
76
|
+
|
|
65
77
|
### Companion dials
|
|
66
78
|
|
|
67
79
|
Same file, same lookup, same fallback-to-default rule:
|
|
@@ -910,11 +910,18 @@ function main() {
|
|
|
910
910
|
// kebab(s) = s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '')
|
|
911
911
|
//
|
|
912
912
|
// WARN (never error) when:
|
|
913
|
-
// - learnings.jsonl
|
|
914
|
-
//
|
|
913
|
+
// - NEITHER a learnings.jsonl entry NOR a valid `evidence-digest` frontmatter
|
|
914
|
+
// scalar is present (the rule's provenance is unresolvable), OR
|
|
915
915
|
// - the matching entry's `expires_at` < now (expired learning).
|
|
916
|
-
//
|
|
917
|
-
//
|
|
916
|
+
//
|
|
917
|
+
// #1101 — the digest branch. `.orchestrator/metrics/learnings.jsonl` is
|
|
918
|
+
// GITIGNORED, so in a fresh clone it does not exist and every generated rule
|
|
919
|
+
// used to warn (measured 2026-08-26: 23 of 23). A rule carrying a valid
|
|
920
|
+
// `evidence-digest: sha256-v1:<64 hex>` is SELF-CONTAINED — its `## Evidence`
|
|
921
|
+
// block plus its own `## Provenance` header fields re-derive the seal with no
|
|
922
|
+
// jsonl lookup — so its provenance is resolvable offline and it must not warn.
|
|
923
|
+
// The digest is EVIDENCE, not a second pointer; see
|
|
924
|
+
// `scripts/lib/reconcile/renderer.mjs` § computeEvidenceDigest.
|
|
918
925
|
// The check is silently skipped (no id pushed) when .claude/rules/ is absent
|
|
919
926
|
// or contains no .md files with auto-generated: true.
|
|
920
927
|
if (!args.skipGeneratedRuleStaleness) {
|
|
@@ -926,15 +933,17 @@ function main() {
|
|
|
926
933
|
// Reads the opening --- ... --- block from a markdown file.
|
|
927
934
|
function extractFrontmatterFields(mdContent) {
|
|
928
935
|
const m = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(stripLeadingRuleHeaderLines(mdContent));
|
|
929
|
-
if (!m) return { autoGenerated: false, learningKey: null, expiresAt: null };
|
|
936
|
+
if (!m) return { autoGenerated: false, learningKey: null, expiresAt: null, evidenceDigest: null };
|
|
930
937
|
const block = m[1];
|
|
931
938
|
const autoGenM = /^auto-generated:\s*(.+)$/m.exec(block);
|
|
932
939
|
const learningKeyM = /^learning-key:\s*(.+)$/m.exec(block);
|
|
933
940
|
const expiresAtM = /^expires-at:\s*(.+)$/m.exec(block);
|
|
941
|
+
const evidenceDigestM = /^evidence-digest:\s*(.+)$/m.exec(block);
|
|
934
942
|
return {
|
|
935
943
|
autoGenerated: autoGenM ? autoGenM[1].trim() === 'true' : false,
|
|
936
944
|
learningKey: learningKeyM ? learningKeyM[1].trim() : null,
|
|
937
945
|
expiresAt: expiresAtM ? expiresAtM[1].trim() : null,
|
|
946
|
+
evidenceDigest: evidenceDigestM ? evidenceDigestM[1].trim() : null,
|
|
938
947
|
};
|
|
939
948
|
}
|
|
940
949
|
|
|
@@ -955,12 +964,20 @@ function main() {
|
|
|
955
964
|
relPath: relative(vaultDir, absPath),
|
|
956
965
|
learningKey: fields.learningKey,
|
|
957
966
|
expiresAt: fields.expiresAt,
|
|
967
|
+
evidenceDigest: fields.evidenceDigest,
|
|
958
968
|
});
|
|
959
969
|
}
|
|
960
970
|
|
|
961
971
|
// No generated rules found → silently skip (don't push the check id).
|
|
962
972
|
if (generatedRules.length === 0) return;
|
|
963
973
|
|
|
974
|
+
// #1101 — a LITERAL COPY of `EVIDENCE_DIGEST_RE` from
|
|
975
|
+
// `scripts/lib/reconcile/renderer.mjs`. Copied, not imported: this checker
|
|
976
|
+
// is a standalone skill script, and importing across the skill/script
|
|
977
|
+
// boundary would add real coupling for one 30-character literal. The two
|
|
978
|
+
// copies are pinned equal by `tests/lib/reconcile/renderer.test.mjs`.
|
|
979
|
+
const EVIDENCE_DIGEST_RE = /^sha256-v1:[0-9a-f]{64}$/;
|
|
980
|
+
|
|
964
981
|
// Slugify function mirroring emitter.mjs `kebab()`.
|
|
965
982
|
const kebab = (s) =>
|
|
966
983
|
String(s)
|
|
@@ -1001,26 +1018,37 @@ function main() {
|
|
|
1001
1018
|
const nowMs = Date.now();
|
|
1002
1019
|
|
|
1003
1020
|
for (const rule of generatedRules) {
|
|
1004
|
-
const { relPath, learningKey, expiresAt } = rule;
|
|
1021
|
+
const { relPath, learningKey, expiresAt, evidenceDigest } = rule;
|
|
1005
1022
|
|
|
1006
1023
|
// If we cannot evaluate the key (no learning-key frontmatter), skip
|
|
1007
1024
|
// silently — avoid false positives on malformed rules.
|
|
1008
1025
|
if (!learningKey) continue;
|
|
1009
1026
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1027
|
+
const hasJsonlEntry = learningsPresent && knownKeys.has(learningKey);
|
|
1028
|
+
const hasValidDigest =
|
|
1029
|
+
typeof evidenceDigest === 'string' && EVIDENCE_DIGEST_RE.test(evidenceDigest);
|
|
1030
|
+
|
|
1031
|
+
if (!hasJsonlEntry && !hasValidDigest) {
|
|
1032
|
+
// NEITHER resolution path is available: the learning is absent from
|
|
1033
|
+
// learnings.jsonl (or the file is missing entirely) AND the rule carries
|
|
1034
|
+
// no self-contained evidence digest, so nothing can vouch for it.
|
|
1012
1035
|
warnings.push({
|
|
1013
1036
|
check: 'generated-rule-staleness',
|
|
1014
1037
|
file: relPath,
|
|
1015
1038
|
line: 1,
|
|
1016
|
-
message: `Auto-generated rule references learning-key '${learningKey}' which is absent from .orchestrator/metrics/learnings.jsonl`,
|
|
1039
|
+
message: `Auto-generated rule references learning-key '${learningKey}' which is absent from .orchestrator/metrics/learnings.jsonl, and the rule carries no valid evidence-digest to verify it offline`,
|
|
1017
1040
|
extracted: learningKey,
|
|
1018
1041
|
});
|
|
1019
1042
|
continue;
|
|
1020
1043
|
}
|
|
1021
1044
|
|
|
1022
|
-
//
|
|
1023
|
-
|
|
1045
|
+
// Provenance resolves — check expiry.
|
|
1046
|
+
// `storedExpiresAt` is only meaningful when the jsonl entry actually
|
|
1047
|
+
// exists. A digest-only rule (fresh clone, or a learning aged out of the
|
|
1048
|
+
// store) is AUTHORITATIVE FOR ITS OWN EXPIRY via frontmatter; reading a
|
|
1049
|
+
// stored value that is not there would make `expiryStr` null and silently
|
|
1050
|
+
// skip the expiry gate for a rule that has a perfectly good `expires-at`.
|
|
1051
|
+
const storedExpiresAt = hasJsonlEntry ? knownKeys.get(learningKey) : null;
|
|
1024
1052
|
// Prefer the frontmatter expires-at on the rule file; fall back to the
|
|
1025
1053
|
// stored expires_at from the learning entry (both should agree, but the
|
|
1026
1054
|
// rule file is authoritative for its own expiry).
|
|
@@ -104,13 +104,13 @@ When the gate above is satisfied, present exactly this AskUserQuestion (AUQ-003
|
|
|
104
104
|
```
|
|
105
105
|
AskUserQuestion({
|
|
106
106
|
questions: [{
|
|
107
|
-
question: "Scope `feature` was requested. How should this run handle
|
|
108
|
-
header: "
|
|
107
|
+
question: "Scope `feature` was requested. How should this run handle it?",
|
|
108
|
+
header: "Scope",
|
|
109
109
|
options: [
|
|
110
|
-
{ label: "Grounded scan (Recommended)", description: "
|
|
111
|
-
{ label: "Also judgment topics", description: "
|
|
112
|
-
{ label: "Route out", description: "No scan
|
|
113
|
-
{ label: "Skip", description: "
|
|
110
|
+
{ label: "Grounded scan (Recommended)", description: "Every finding is tied to a file and line and is verified before it can become an issue. Cost: two extra probes (intent-drift, stubbed-dead-feature)." },
|
|
111
|
+
{ label: "Also judgment topics", description: "Same scan, plus open product questions (opportunity framing, personas) kept as notes. They never become issues; after Phase 5 you pick where they go." },
|
|
112
|
+
{ label: "Route out", description: "No scan at all. You get a pointer to /brainstorm (product ideation) or /grill (assumption stress-test) instead." },
|
|
113
|
+
{ label: "Skip", description: "Drops `feature` (the probes for half-built and drifted features) from this run; the other scopes still run." }
|
|
114
114
|
],
|
|
115
115
|
multiSelect: false
|
|
116
116
|
}]
|
|
@@ -125,12 +125,12 @@ AskUserQuestion({
|
|
|
125
125
|
```
|
|
126
126
|
AskUserQuestion({
|
|
127
127
|
questions: [{
|
|
128
|
-
question: "
|
|
129
|
-
header: "
|
|
128
|
+
question: "Where should the collected judgment topics go?",
|
|
129
|
+
header: "Topics",
|
|
130
130
|
options: [
|
|
131
|
-
{ label: "Inline synthesis (Recommended)", description: "
|
|
132
|
-
{ label: "Route to /brainstorm", description: "
|
|
133
|
-
{ label: "Route to /plan feature", description: "
|
|
131
|
+
{ label: "Inline synthesis (Recommended)", description: "Sketches an outcome/persona pass into `### Judgment Topics (non-verified)` (a report section that never becomes issues). Cost: no second run." },
|
|
132
|
+
{ label: "Route to /brainstorm", description: "Hands the topics to /brainstorm as its opening context, for a full question-and-answer design dialogue." },
|
|
133
|
+
{ label: "Route to /plan feature", description: "Hands the topics to /plan feature as its opening context, for feature-PRD scoping." }
|
|
134
134
|
],
|
|
135
135
|
multiSelect: false
|
|
136
136
|
}]
|
|
@@ -370,14 +370,16 @@ For each Critical or High finding, use AskUserQuestion (on Codex CLI where AskUs
|
|
|
370
370
|
```
|
|
371
371
|
AskUserQuestion({
|
|
372
372
|
questions: [{
|
|
373
|
-
question: "<finding
|
|
374
|
-
header: "
|
|
373
|
+
question: "<severity> finding in <file_path> — what should happen with it?",
|
|
374
|
+
header: "Finding",
|
|
375
375
|
options: [
|
|
376
|
-
{ label: "Create issue (<severity>)", description: "
|
|
377
|
-
|
|
378
|
-
{ label: "
|
|
379
|
-
{ label: "Dismiss --
|
|
380
|
-
|
|
376
|
+
{ label: "Create issue (<severity>)", description: "Files it as priority::<severity>, so it is tracked outside this session. The code below is copied into the issue body.",
|
|
377
|
+
preview: "<finding title>\n\n<file_path>:<line_number>\n```\n<matched_text with +/-3 lines context>\n```\n\n<description>\n\nRecommended fix: <recommended_fix>" },
|
|
378
|
+
{ label: "Adjust priority", description: "Same issue, a priority you pick — this question then comes back with the new label." },
|
|
379
|
+
{ label: "Dismiss -- intentional", description: "The code is deliberate. Nothing is filed, and the finding stays only in this run's report." },
|
|
380
|
+
{ label: "Dismiss -- false positive", description: "The probe misread the code. Nothing is filed; worth reporting if the same probe misfires again." }
|
|
381
|
+
],
|
|
382
|
+
multiSelect: false
|
|
381
383
|
}]
|
|
382
384
|
})
|
|
383
385
|
```
|
|
@@ -391,13 +393,15 @@ Group remaining findings by category. For each category with medium/low findings
|
|
|
391
393
|
```
|
|
392
394
|
AskUserQuestion({
|
|
393
395
|
questions: [{
|
|
394
|
-
question: "[N] medium/low findings in [category]
|
|
395
|
-
header: "
|
|
396
|
+
question: "Create issues for all [N] medium/low findings in [category]?",
|
|
397
|
+
header: "Findings",
|
|
396
398
|
options: [
|
|
397
|
-
{ label: "Accept all (Recommended)", description: "
|
|
398
|
-
|
|
399
|
-
{ label: "
|
|
400
|
-
|
|
399
|
+
{ label: "Accept all (Recommended)", description: "Medium and low findings are cheap to file and cheap to close. Cost: [N] issues, roughly one second apart.",
|
|
400
|
+
preview: "1. [title] -- [file_path]:[line] ([severity])\n2. [title] -- [file_path]:[line] ([severity])\n..." },
|
|
401
|
+
{ label: "Review individually", description: "One question per finding, same options as the critical ones. Cost: [N] more prompts." },
|
|
402
|
+
{ label: "Dismiss all", description: "Nothing is filed for this category. The findings stay in this run's report only." }
|
|
403
|
+
],
|
|
404
|
+
multiSelect: false
|
|
401
405
|
}]
|
|
402
406
|
})
|
|
403
407
|
```
|
|
@@ -113,7 +113,7 @@ const res = claimRepo({ repoRoot: R, sessionId, mode, ttlHours, semanticSessionI
|
|
|
113
113
|
Or reuse the primitive directly: `acquire({ sessionId, mode, ttlHours, repoRoot, semanticSessionId })` from `scripts/lib/session-lock.mjs`. The claim is a `linkSync` create-or-fail = **atomic**.
|
|
114
114
|
|
|
115
115
|
- **`ok: true`** → the claim is held. Proceed to Phase 4.
|
|
116
|
-
- **`ok: false`** (race lost / busy — reasons: `active`, `stale-
|
|
116
|
+
- **`ok: false`** (race lost / busy — reasons: `active`, `stale-heartbeat`, `fs-error`, …) → **exclude R**, re-rank the remaining free candidates (drop R from `free`, re-run Phase 1's rank step), and re-present Phase 2. Loop until a claim succeeds or no free candidate remains (then Phase 5).
|
|
117
117
|
|
|
118
118
|
Do NOT reinvent the claim — always go through `claimRepo`/`acquire`. The `ok:false` path is the load-bearing concurrency guard: two parallel dispatchers can both recommend R, but only one wins the `linkSync`; the loser must re-rank, never force.
|
|
119
119
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eli5
|
|
3
|
+
description: Explain a topic like I'm a 5 year old — restate my last output, or a named topic, in plain words without dropping a single fact. Use when the user types /eli5 [topic], or says an answer was too technical, too long, or unclear about what he now has to do.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Grep, Glob, Bash
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# eli5
|
|
9
|
+
|
|
10
|
+
Say it again in plain words. Same facts, in the order he needs them.
|
|
11
|
+
|
|
12
|
+
## The frame
|
|
13
|
+
|
|
14
|
+
**Write for someone who knows this project but has not seen what you just saw.**
|
|
15
|
+
|
|
16
|
+
He owns this repo. He is not missing knowledge, he is missing observation — he did not watch the command run or read the file it points at. Write across, not down. `.claude/rules/ask-via-tool.md` § AUQ-006 and `skills/session-start/soul.md` § Register are the canonical statement of this register; apply them, do not restate them.
|
|
17
|
+
|
|
18
|
+
## What to restate
|
|
19
|
+
|
|
20
|
+
- `/eli5` — my last substantial output in this conversation. If there is none yet, say so instead of inventing a topic.
|
|
21
|
+
- `/eli5 <topic>` — that topic (`$ARGUMENTS`), grounded in what THIS session already measured: name the file, command, or record it came from. If it was never measured here, say that rather than filling the gap from memory.
|
|
22
|
+
|
|
23
|
+
Answer in the operator's language: `owner.language` in `~/.config/session-orchestrator/owner.yaml`, falling back to `en` when that file is missing, unreadable, or the key is absent — and follow the operator's own language the moment he writes in another one.
|
|
24
|
+
|
|
25
|
+
## Two limits, and they are the whole skill
|
|
26
|
+
|
|
27
|
+
**1. Say more simply what actually happens — introduce nothing that does not exist.**
|
|
28
|
+
Test: delete every noun the system does not contain. Sentence still true and complete → it was no analogy. Sentence collapses → describe what actually happens instead.
|
|
29
|
+
✓ "Waiting means the other session finishes first." ✗ "Think of the session as a level crossing."
|
|
30
|
+
|
|
31
|
+
**2. Simplifying removes words, never facts.** If a path, a number, an error code, an identifier, or an instruction to act disappears, that is data loss, not simplification. The mechanical decider: **could the token you are about to cut ever appear in a `grep`? Then it stays.** `skills/session-start/soul.md` § "Never traded for brevity" outranks every brevity instruction in this file.
|
|
32
|
+
|
|
33
|
+
## Shape
|
|
34
|
+
|
|
35
|
+
Line 1 answers the question he actually has: **do I have to do something now, and what happens if I don't?** Then the facts, in the order he needs them — not the order you found them.
|
|
36
|
+
|
|
37
|
+
This is a terminal, so there is no picture to draw. The second channel is the `preview` field on an `AskUserQuestion` option: when the options differ in something literal — a diff, a title, a config block, a file list — put that text there and he reads the thing instead of a description of it.
|
|
38
|
+
|
|
39
|
+
## What this is not
|
|
40
|
+
|
|
41
|
+
- **Not shorter by default.** Eight lines before may be eight lines after. Reorder first; cut only filler.
|
|
42
|
+
- **Not a children's explanation.** The label is a poster, the reader is an expert who was not in the room.
|
|
43
|
+
- **Not a second attempt at the answer.** If the first answer was wrong, fix the answer — `/eli5` restates, it never re-derives.
|
package/skills/evolve/SKILL.md
CHANGED
|
@@ -248,8 +248,8 @@ Present extracted patterns to the user for confirmation. Use AskUserQuestion wit
|
|
|
248
248
|
```
|
|
249
249
|
AskUserQuestion({
|
|
250
250
|
questions: [{
|
|
251
|
-
question: "Which
|
|
252
|
-
header: "
|
|
251
|
+
question: "Which of the patterns extracted from this session's history should be saved?",
|
|
252
|
+
header: "Speichern?",
|
|
253
253
|
options: [
|
|
254
254
|
{
|
|
255
255
|
label: "[type] subject",
|
|
@@ -455,19 +455,18 @@ Use AskUserQuestion with options:
|
|
|
455
455
|
AskUserQuestion({
|
|
456
456
|
questions: [{
|
|
457
457
|
question: "What would you like to do with your learnings?",
|
|
458
|
-
header: "
|
|
458
|
+
header: "Learnings",
|
|
459
459
|
options: [
|
|
460
|
-
{ label: "
|
|
461
|
-
{ label: "
|
|
462
|
-
{ label: "Delete specific learnings", description: "
|
|
463
|
-
{ label: "
|
|
464
|
-
{ label: "Done — no changes", description: "Exit without changes" }
|
|
460
|
+
{ label: "Confidence ändern", description: "Pick the learnings, then the direction: +0.15 or -0.2. Cheapest fix when a learning is merely mis-weighted." },
|
|
461
|
+
{ label: "Ablauf verlängern", description: "Keeps a still-useful learning alive: its expiry date moves to today plus the configured window. Confidence is untouched." },
|
|
462
|
+
{ label: "Delete specific learnings", description: "Takes the selected learnings out of the store. They are archived rather than shredded, but they stop influencing anything." },
|
|
463
|
+
{ label: "Done — no changes", description: "Leaves the store exactly as it is and ends the review. Nothing is written." }
|
|
465
464
|
]
|
|
466
465
|
}]
|
|
467
466
|
})
|
|
468
467
|
```
|
|
469
468
|
|
|
470
|
-
If user selects "
|
|
469
|
+
If user selects "Confidence ändern", "Ablauf verlängern", or "Delete specific learnings", present a follow-up AskUserQuestion with `multiSelect: true` listing all learnings by `# | type | subject` so the user can select which ones to modify. For "Confidence ändern" the same follow-up also asks for the direction — **Boost** (+0.15) or **Reduce** (-0.2). Both operations are unchanged; only the point at which the direction is chosen moved, because a single AskUserQuestion accepts at most 4 options and the previous list had 5.
|
|
471
470
|
|
|
472
471
|
> On Codex CLI where AskUserQuestion is unavailable, present as a numbered Markdown list.
|
|
473
472
|
|
|
@@ -9,7 +9,7 @@ model-preference-cursor: claude-sonnet-4-6
|
|
|
9
9
|
description: >
|
|
10
10
|
Use this skill when performing VCS operations on GitLab or GitHub repositories — creating, updating, or
|
|
11
11
|
closing issues and MRs, applying label taxonomy, running `glab`/`gh` CLI commands, or resolving project
|
|
12
|
-
|
|
12
|
+
paths dynamically. Acts as the single source of truth for CLI command syntax and label conventions;
|
|
13
13
|
consuming skills reference this rather than duplicating logic. Triggers: "create a GitLab issue", "list
|
|
14
14
|
open MRs", "apply priority label", "how do I resolve the project ID", "what's the carryover issue
|
|
15
15
|
template". <example>Context: session-end needs to file a carryover issue for an incomplete task. user:
|
|
@@ -45,7 +45,7 @@ syntax inline. This skill is the single source of truth for all VCS operations.
|
|
|
45
45
|
When a skill needs VCS operations, include this reference block in its instructions:
|
|
46
46
|
|
|
47
47
|
> **VCS Reference:** Detect the VCS platform per the "VCS Auto-Detection" section of the gitlab-ops skill.
|
|
48
|
-
> Use CLI commands per the "Common CLI Commands" section. For
|
|
48
|
+
> Use CLI commands per the "Common CLI Commands" section. For GitLab API operations, see "Canonical Project Identity."
|
|
49
49
|
|
|
50
50
|
**Canonical commands:** All `glab` and `gh` command syntax — flags, output formats,
|
|
51
51
|
pagination options — is defined in the "Common CLI Commands" section below. Consuming
|
|
@@ -57,34 +57,35 @@ command variant not listed there, add it to this file first, then reference it.
|
|
|
57
57
|
- Any skill-specific *parameters* they pass to commands (e.g., label names, issue templates)
|
|
58
58
|
- They should NOT include raw `glab`/`gh` invocations or detection snippets
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## Canonical Project Identity
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
GitLab REST endpoints accept a URL-encoded `namespace/project` path. Select the GitLab host and project path explicitly; never derive a numeric project ID from `glab repo view`, search `projects?search=`, or use `:id` placeholders. Those forms can resolve through the ambient working directory or a stale search result and target another project after a rename, fork, or scaffold.
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
Set the identity once per operation sequence and reuse the encoded identifier without encoding it again:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
GITLAB_HOST="<selected GitLab hostname>"
|
|
68
|
+
GROUP_PATH="<selected group path>"
|
|
69
|
+
PROJECT_NAME="<selected project name>"
|
|
70
|
+
PROJECT_PATH="$GROUP_PATH/$PROJECT_NAME"
|
|
71
|
+
ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$PROJECT_PATH")"
|
|
72
|
+
```
|
|
69
73
|
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
For a link target in another project, use the same path-first shape instead of a numeric ID:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
TARGET_PROJECT_PATH="<target namespace>/<target project>"
|
|
78
|
+
TARGET_ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$TARGET_PROJECT_PATH")"
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
Pass `--hostname "$GITLAB_HOST"` to every `glab api` call. The endpoint itself then pins the project, including directly after creating a repository when the current directory does not yet identify the new project.
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
GitHub continues to use an `owner/repo` slug; `gh repo` takes it positionally and rejects `-R`:
|
|
77
84
|
|
|
78
85
|
```bash
|
|
79
|
-
|
|
80
|
-
glab api "projects?search=<project-name>" | python3 -c "import json,sys; [print(p['id'], p['path_with_namespace']) for p in json.load(sys.stdin)]"
|
|
81
|
-
|
|
82
|
-
# GitHub — resolve repo details
|
|
83
|
-
gh api "repos/<owner>/<name>" --jq '.full_name'
|
|
86
|
+
gh repo view --json nameWithOwner -q '.nameWithOwner'
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
**Note:** Some API calls require numeric project IDs (GitLab) or `owner/repo` slugs (GitHub). Always resolve dynamically from the project name.
|
|
87
|
-
|
|
88
89
|
### Canonical enumeration pattern
|
|
89
90
|
|
|
90
91
|
To enumerate ALL projects (or issues) in a group, a single page is never the whole result — paginate and guard against silent truncation:
|
|
@@ -93,7 +94,7 @@ To enumerate ALL projects (or issues) in a group, a single page is never the who
|
|
|
93
94
|
# GitLab — paginate a group's projects, following x-next-page until empty
|
|
94
95
|
page=1
|
|
95
96
|
while [ -n "$page" ]; do
|
|
96
|
-
resp=$(glab api "groups/<group-id>/projects?include_subgroups=true&per_page=100&page=$page" --include)
|
|
97
|
+
resp=$(glab api --hostname "$GITLAB_HOST" "groups/<group-id>/projects?simple=true&include_subgroups=true&per_page=100&page=$page" --include)
|
|
97
98
|
# parse the response body ($resp) for project ids/paths here, deduping by id.
|
|
98
99
|
# Then advance by reading the `x-next-page` response header — an empty value
|
|
99
100
|
# means this was the last page, so the loop exits (the guard above is what breaks).
|
|
@@ -146,13 +147,16 @@ done
|
|
|
146
147
|
|
|
147
148
|
## Issue Linking (`blocks` / `is_blocked_by`)
|
|
148
149
|
|
|
149
|
-
GitLab's native issue-link types `blocks` and `is_blocked_by` (`glab api -X POST projects
|
|
150
|
+
GitLab's native issue-link types `blocks` and `is_blocked_by` (`glab api --silent --hostname "$GITLAB_HOST" -X POST "projects/${ENCODED_PROJECT_PATH}/issues/${ISSUE_IID}/links" -f target_project_id="$TARGET_ENCODED_PROJECT_PATH" -f target_issue_iid="$OTHER_ISSUE_IID" -f link_type="$LINK_TYPE"`) are a **Premium/Ultimate license feature**. Set `LINK_TYPE` to `blocks` or `is_blocked_by`; the target accepts an encoded project path, so no numeric project ID is needed. On a Free/Core-tier GitLab instance this call returns **HTTP 403** — a license-gate signal, not an auth/permission failure. Do not retry with different credentials or escalate as an auth bug.
|
|
150
151
|
|
|
151
152
|
**Fallback (non-Premium instances):**
|
|
152
153
|
1. **Use `relates_to` instead** — `link_type=relates_to` is available on every GitLab tier (no ordering semantics, just an unscoped relation). Same API shape, only the `link_type` value changes:
|
|
153
154
|
```bash
|
|
154
|
-
glab api -X POST
|
|
155
|
-
|
|
155
|
+
glab api --silent --hostname "$GITLAB_HOST" -X POST \
|
|
156
|
+
"projects/${ENCODED_PROJECT_PATH}/issues/${ISSUE_IID}/links" \
|
|
157
|
+
-f target_project_id="$TARGET_ENCODED_PROJECT_PATH" \
|
|
158
|
+
-f target_issue_iid="$OTHER_ISSUE_IID" \
|
|
159
|
+
-f link_type=relates_to
|
|
156
160
|
```
|
|
157
161
|
2. **Document the blocking semantics in the issue body** — since `relates_to` carries no ordering meaning, add an explicit ordering note to both issues, e.g. `⚠ Ordering: erst #<blocker_iid>, dann dieses Issue — blocks-Link nicht verfügbar (non-Premium)`.
|
|
158
162
|
3. **Recognize the 403 as a license signal, not an auth error** — before assuming a token/scope problem, try `relates_to` on the same project pair: if `relates_to` succeeds where `blocks`/`is_blocked_by` 403s, the license gate — not authentication — is the cause.
|
|
@@ -187,14 +191,14 @@ glab mr merge -R <OWNER>/<REPO> <MR_IID> # Mer
|
|
|
187
191
|
glab pipeline list -R <OWNER>/<REPO> --per-page 5 # Recent pipelines
|
|
188
192
|
glab pipeline status -R <OWNER>/<REPO> <ID> # Pipeline details
|
|
189
193
|
|
|
190
|
-
# API (no --repo exists here — the endpoint
|
|
191
|
-
glab api
|
|
192
|
-
glab api
|
|
194
|
+
# API (no --repo exists here — the encoded endpoint and explicit host identify the target)
|
|
195
|
+
glab api --hostname "$GITLAB_HOST" "projects/${ENCODED_PROJECT_PATH}/issues?state=opened&per_page=50"
|
|
196
|
+
glab api --hostname "$GITLAB_HOST" "projects/${ENCODED_PROJECT_PATH}/milestones?state=active"
|
|
193
197
|
```
|
|
194
198
|
|
|
195
199
|
**Label update caveat (PUT-replaces, not additive):** `glab issue update --label` (and the underlying GitLab labels API) PUT-REPLACES the entire label set — it does not add to the existing set. To change a single label you must pass the FULL desired label list, or use the dedicated add/remove operations, which are themselves unreliable across `glab` versions. Preferred safe pattern: use `--label` (adds) together with `--unlabel` (removes) on `glab issue update` when your installed `glab` version supports both; otherwise read the current labels first, compute the full new set, and PUT once. The same PUT-replace semantics apply to `glab mr update --label`.
|
|
196
200
|
|
|
197
|
-
**Close verification:** after `glab issue close <IID>`, always verify the close actually landed — re-read the issue (`glab issue view <IID>`) and confirm `state: closed` in the output. A stale
|
|
201
|
+
**Close verification:** after `glab issue close <IID>`, always verify the close actually landed — re-read the issue (`glab issue view <IID>`) and confirm `state: closed` in the output. A stale or wrong project path, or a silent 404, can report local success while closing nothing; use the canonical project identity above for API operations rather than resolving a numeric ID.
|
|
198
202
|
|
|
199
203
|
**Commit-body close-keyword footgun:** GitLab (and GitHub) auto-close an issue when a commit pushed to the default branch contains a close keyword — `close`/`closes`/`closed`/`fix`/`fixes`/`fixed`/`resolve`/`resolves`/`resolved` — followed by `#N` ANYWHERE in the commit body, not just the subject line. This fires even inside a negation ("does NOT close #N") — the platform pattern-matches the keyword + issue reference; it does not parse English negation, so the negation offers no protection. Rule: when a commit body needs to MENTION an issue without closing intent, always use a non-closing reference — `refs #N`, `part of #N`, `siehe #N` — never a close-keyword verb next to the number, negated or not.
|
|
200
204
|
|
package/skills/grill/SKILL.md
CHANGED
|
@@ -66,7 +66,7 @@ Walk the decision tree **one question at a time**. For each branch, in order:
|
|
|
66
66
|
AskUserQuestion({
|
|
67
67
|
questions: [{
|
|
68
68
|
question: "Your code cancels whole Orders, but the PRD says a customer can cancel one line item. Which is the real model?",
|
|
69
|
-
header: "
|
|
69
|
+
header: "Cancel scope",
|
|
70
70
|
options: [
|
|
71
71
|
{ label: "Line-item cancellation (Recommended)", description: "Matches the PRD intent. Cost: new partial-refund path + Order stays open after one item is voided." },
|
|
72
72
|
{ label: "Whole-order only", description: "Matches today's code. Cost: contradicts the stated user story — re-scope the PRD." },
|
|
@@ -118,12 +118,12 @@ Per the user's configured behaviour, the grill ends with a hand-off and an OPTIO
|
|
|
118
118
|
AskUserQuestion({
|
|
119
119
|
questions: [{
|
|
120
120
|
question: "Grill complete. How do you want to proceed?",
|
|
121
|
-
header: "
|
|
121
|
+
header: "Hand-off",
|
|
122
122
|
options: [
|
|
123
|
-
{ label: "
|
|
124
|
-
{ label: "Write grill summary only", description: "
|
|
125
|
-
{ label: "Hand off to /plan feature — no file", description: "
|
|
126
|
-
{ label: "Done — no file, no hand-off", description: "The grilling itself was the value
|
|
123
|
+
{ label: "Summary + /plan feature (Recommended)", description: "Writes the resolved decisions to docs/specs/ (a folder of markdown notes), then hands them to planning. Cost: one file." },
|
|
124
|
+
{ label: "Write grill summary only", description: "Same file, no planning step. The decisions keep, so you can hand them off later." },
|
|
125
|
+
{ label: "Hand off to /plan feature — no file", description: "Carries the decisions straight into planning. They then live only in this conversation." },
|
|
126
|
+
{ label: "Done — no file, no hand-off", description: "The grilling itself was the value. Nothing is written, nothing is handed on." }
|
|
127
127
|
],
|
|
128
128
|
multiSelect: false
|
|
129
129
|
}]
|
package/skills/grill/soul.md
CHANGED
|
@@ -76,6 +76,22 @@ This is the tightest of the orchestrator's budgets by design. A turn is structur
|
|
|
76
76
|
- Shape: explain which tactic you are applying and why it bites here, name the branches of the decision tree you are deferring, define unfamiliar terms on first use.
|
|
77
77
|
- Escalation: `expand <topic>` — see § Escalation above.
|
|
78
78
|
|
|
79
|
+
### Register — how a sentence reads
|
|
80
|
+
|
|
81
|
+
The budgets above set *how much* you say; the register sets *how*. It is
|
|
82
|
+
defined once, in `skills/session-start/soul.md` § "Register — how a sentence
|
|
83
|
+
reads", and binds here unchanged: the frame ("write for someone who knows this
|
|
84
|
+
project but has not seen what you just saw"), the plain-words test with its
|
|
85
|
+
five worked cases, and its precedence over § "Never traded for brevity" above.
|
|
86
|
+
Read it there. It is not repeated here on purpose — the § Output Levels intro
|
|
87
|
+
sentence already exists in four copies across the four souls with nothing
|
|
88
|
+
checking their parity, and a fifth copied rule would drift the same way. A
|
|
89
|
+
pointer cannot.
|
|
90
|
+
|
|
91
|
+
Note the one place register and adversarial posture meet: a challenge is
|
|
92
|
+
plainer, never softer. "Say it more simply" never becomes "say it less
|
|
93
|
+
sharply" — the contradiction still lands, in shorter words.
|
|
94
|
+
|
|
79
95
|
### Companion dials
|
|
80
96
|
|
|
81
97
|
Same file, same lookup, same fallback-to-default rule:
|