session-orchestrator 3.21.0 → 3.22.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/rules/000-session-orchestrator.mdc +3 -2
- package/.cursor/rules/040-discovery.mdc +6 -6
- package/.cursor/rules/050-plan.mdc +8 -8
- package/CHANGELOG.md +101 -0
- package/README.md +10 -10
- package/agents/memory-proposal-collector.md +6 -4
- package/commands/eli5.md +33 -0
- package/commands/release.md +5 -3
- package/commands/test.md +2 -2
- package/docs/components.md +6 -5
- package/docs/scope-collision-guard.md +3 -3
- package/docs/session-config-reference.md +31 -8
- package/hooks/_lib/lock-bootstrap.mjs +19 -13
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +11 -1
- package/hooks/on-session-end.mjs +24 -92
- package/hooks/on-session-start.mjs +195 -104
- package/hooks/pre-auq-clarity.mjs +787 -0
- package/hooks/pre-bash-issue-budget.mjs +17 -18
- package/package.json +3 -1
- package/pi/prompts/eli5.md +12 -0
- package/scripts/auq-audit.mjs +825 -0
- package/scripts/autopilot.mjs +7 -8
- 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/ci-status-banner.mjs +63 -57
- package/scripts/lib/config/dispatcher-autonomy-capture.mjs +32 -9
- package/scripts/lib/config/vault-integration.mjs +12 -1
- package/scripts/lib/dispatcher/rank.mjs +4 -7
- package/scripts/lib/gates/gate-full.mjs +3 -3
- package/scripts/lib/gates/gate-helpers.mjs +17 -6
- package/scripts/lib/io.mjs +239 -0
- package/scripts/lib/issue-budget.mjs +63 -9
- package/scripts/lib/owner-interview.mjs +78 -32
- package/scripts/lib/peer-discovery.mjs +73 -22
- package/scripts/lib/project-hygiene.mjs +64 -4
- package/scripts/lib/reconcile/renderer.mjs +17 -4
- 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/spiral-carryover.mjs +23 -2
- package/scripts/lib/state-md/mission-status.mjs +147 -50
- package/scripts/lib/validate/check-auq-clarity.mjs +274 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +30 -0
- package/scripts/lib/validate/check-rules.mjs +153 -9
- package/scripts/lib/vault-backfill/glab.mjs +91 -58
- package/scripts/lib/vault-backfill/manifest.mjs +28 -8
- package/scripts/lib/vcs-repo-spec.mjs +182 -13
- package/scripts/lib/wave-resource-gate.mjs +67 -73
- package/scripts/materialize-wave-scope.mjs +281 -0
- package/scripts/release.mjs +443 -122
- package/scripts/run-quality-gate.mjs +14 -0
- package/scripts/validate-plugin.mjs +3 -0
- package/scripts/validate-wave-scope.mjs +6 -1
- package/scripts/vault-backfill.mjs +32 -5
- package/skills/_shared/parallel-aware-auq.md +30 -24
- package/skills/_shared/parallel-aware-preamble.md +31 -2
- package/skills/_shared/state-ownership.md +32 -6
- package/skills/bootstrap/SKILL.md +2 -1
- package/skills/brainstorm/SKILL.md +18 -18
- package/skills/brainstorm/soul.md +12 -0
- package/skills/discovery/SKILL.md +28 -24
- 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/memory-cleanup/SKILL.md +2 -2
- package/skills/npm-publish/SKILL.md +4 -4
- package/skills/peekaboo-driver/SKILL.md +3 -3
- 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 +3 -3
- package/skills/session-end/SKILL.md +53 -20
- package/skills/session-end/phase-3-6-tail.md +37 -2
- package/skills/session-start/SKILL.md +69 -35
- 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/soul.md +110 -0
- package/skills/test-runner/SKILL.md +2 -2
- package/skills/using-orchestrator/SKILL.md +1 -1
- package/skills/wave-executor/wave-loop.md +27 -5
- package/skills/write-executable-plan/SKILL.md +6 -6
- 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/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:
|
|
@@ -246,8 +246,8 @@ const peerWarning = wt.activePeer
|
|
|
246
246
|
|
|
247
247
|
AskUserQuestion({
|
|
248
248
|
questions: [{
|
|
249
|
-
question: `
|
|
250
|
-
header: "
|
|
249
|
+
question: `Auto-promoted worktree ${path.basename(wt.wtPath)} is ${ageDays}d old (branch ${wt.branch}).${peerWarning} Remove?`,
|
|
250
|
+
header: "Worktree",
|
|
251
251
|
multiSelect: false,
|
|
252
252
|
options: [
|
|
253
253
|
{
|
|
@@ -7,7 +7,7 @@ description: Use when publishing this package to npm — a version release (npm
|
|
|
7
7
|
|
|
8
8
|
# npm-publish — token auth, and the calls the script cannot make
|
|
9
9
|
|
|
10
|
-
> **The release itself is `/release` → `scripts/release.mjs`.** That script mechanizes the whole sequence: version surfaces, CHANGELOG gate, drift sweep, tag/registry collision, CI, leakage gate, publish, tag-after-
|
|
10
|
+
> **The release itself is `/release` → `scripts/release.mjs`.** That script mechanizes the whole sequence: version surfaces, CHANGELOG gate, drift sweep, tag/registry collision, CI, leakage gate, publish, the target-confirmed npm receipt boundary, tag-after-receipt, push to both remotes, GitHub-release handling, and live-site poll. This skill does not restate it.
|
|
11
11
|
>
|
|
12
12
|
> What lives here is the half a script cannot own: the **token setup**, the **auth failure diagnosis**, and the **judgement calls** — which version, what a leak means, when to abort rather than repair.
|
|
13
13
|
|
|
@@ -39,7 +39,7 @@ The script gates mechanics. These three are yours, and it will not make them for
|
|
|
39
39
|
|
|
40
40
|
**2. What a leak means when one is found.** A hit from the leakage gate is not a pattern to silence. Decide which of two it is: a real leak (fix `package.json` `files`, re-pack, re-check) or genuine over-matching (fix `LEAKAGE_PATTERNS` in `scripts/release.mjs` **with a test**). There is no third option, and neither is "publish anyway and clean it up in the next version" — an npm publish is not revocable, and unpublishing burns the version number permanently. Operator handling detail: `docs/distribution/npm-publish-checklist.md` § 3.
|
|
41
41
|
|
|
42
|
-
**3. When to abort instead of repair.** Abort — do not patch forward — when the failure is upstream of the
|
|
42
|
+
**3. When to abort instead of repair.** Abort — do not patch forward — when the failure is upstream of the target-confirmed npm receipt: a red preflight row, a lagging `github` mirror, CI not green on the exact commit, a dead token, or a publish that did not issue the target receipt. These are cheap to fix and re-run from the top. Repair-in-place is only appropriate *after* that receipt, where the version is already immutable: registry propagation, a missing GitHub release, or a lagging site deploy can be reconciled because npm already has the correct artifact. When `--publish` reports **Post-publish reconciliation required**, **do not rerun `--publish`**; repair the listed state directly. `commands/release.md` § Abort criteria is the operative list.
|
|
43
43
|
|
|
44
44
|
## Failure-mode table
|
|
45
45
|
|
|
@@ -48,13 +48,13 @@ The script gates mechanics. These three are yours, and it will not make them for
|
|
|
48
48
|
| `E403 ... Two-factor authentication or granular access token with bypass 2fa enabled is required` — no OTP prompt | Account has no 2FA enrolled AND token (if any) lacks Bypass-2FA | Create granular token with all four requirements above, or enroll 2FA |
|
|
49
49
|
| Same E403 despite a fresh token | Token created without the Bypass-2FA checkbox, or Read-only, or package-scoped on a first publish | Re-create: RW + All packages + Bypass-2FA |
|
|
50
50
|
| `npm whoami` silent or non-zero | Token expired, or `.env.local` missing | Re-create the token; do not proceed — the preflight fails this row on purpose |
|
|
51
|
-
| `E404` on `npm view` after publish | Registry propagation (rare, seconds)
|
|
51
|
+
| `E404` on `npm view` after a target-confirmed publish receipt | Registry propagation (rare, seconds) | Let the script finish its tag/push/GitHub/site tail, then reconcile the registry result; do **not** rerun `--publish` |
|
|
52
52
|
| `ENEEDAUTH` | No login/token at all | Token flow above, or `npm login` |
|
|
53
53
|
| OTP prompt appears but flow is non-interactive (`!`-prefix, script) | No TTY for the prompt | Use the token flow, or a real terminal |
|
|
54
54
|
|
|
55
55
|
## Post-publish — the human half
|
|
56
56
|
|
|
57
|
-
`--publish`
|
|
57
|
+
`--publish` attempts registry verification and polls the live site itself. A target-confirmed receipt plus a delayed registry result is a reconciliation outcome, not a failed publish or a retry instruction. What still needs a person:
|
|
58
58
|
|
|
59
59
|
1. **Rotate/delete the token** at https://www.npmjs.com/settings/<user>/tokens. A token that ever transited a conversation, a screenshot, or any log is burned — rotate immediately.
|
|
60
60
|
2. **pi.dev gallery**: indexing is asynchronous — check https://pi.dev/packages later; do not block on it.
|
|
@@ -96,10 +96,10 @@ For each `${PERM_NAME}` in `$MISSING`:
|
|
|
96
96
|
```
|
|
97
97
|
AskUserQuestion({
|
|
98
98
|
questions: [{
|
|
99
|
-
question: `${PERM_NAME}
|
|
100
|
-
header:
|
|
99
|
+
question: `${PERM_NAME} is not granted. Enable the terminal entry under System Settings > Privacy & Security, then confirm.`,
|
|
100
|
+
header: "Zugriff",
|
|
101
101
|
options: [
|
|
102
|
-
{ label: "Granted — continue (Recommended)", description:
|
|
102
|
+
{ label: "Granted — continue (Recommended)", description: "I enabled the terminal entry in that pane — the driver then checks again and carries on if the grant took effect." },
|
|
103
103
|
{ label: "Skip this run", description: "Abort peekaboo-driver. Test-runner will record a framework-error finding." }
|
|
104
104
|
],
|
|
105
105
|
multiSelect: false
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -281,17 +281,17 @@ If any criterion is FAIL:
|
|
|
281
281
|
2. Revise the affected PRD sections
|
|
282
282
|
3. Re-submit to the reviewer
|
|
283
283
|
|
|
284
|
-
Maximum 3 iterations. After 3 iterations with remaining issues,
|
|
284
|
+
Maximum 3 iterations. After 3 iterations with remaining issues, list the flagged points in plain text (they are context, not a choice), then ask via AskUserQuestion:
|
|
285
285
|
|
|
286
286
|
```
|
|
287
287
|
AskUserQuestion({
|
|
288
288
|
questions: [{
|
|
289
|
-
question: "The
|
|
289
|
+
question: "The reviewer still flags [N] points after 3 revision rounds. Proceed anyway?",
|
|
290
290
|
header: "PRD Review",
|
|
291
291
|
options: [
|
|
292
|
-
{ label: "Accept as-is (Recommended)", description: "
|
|
293
|
-
{ label: "Manual edit", description: "
|
|
294
|
-
{ label: "Re-run review", description: "
|
|
292
|
+
{ label: "Accept as-is (Recommended)", description: "Three rounds did not close them, so a fourth probably will not. The flags then stay in the PRD and travel into the issues filed from it." },
|
|
293
|
+
{ label: "Manual edit", description: "You edit the PRD yourself; the flow waits, then re-runs the reviewer on your version." },
|
|
294
|
+
{ label: "Re-run review", description: "One more revision round. Cost: another reviewer pass, and the same points may come back unchanged." }
|
|
295
295
|
],
|
|
296
296
|
multiSelect: false
|
|
297
297
|
}]
|
|
@@ -300,16 +300,16 @@ AskUserQuestion({
|
|
|
300
300
|
|
|
301
301
|
### 5.3 User Review Gate
|
|
302
302
|
|
|
303
|
-
After the reviewer passes (or user accepts), present the final PRD:
|
|
303
|
+
After the reviewer passes (or user accepts), present the final PRD in plain text — path plus a short section summary — then ask:
|
|
304
304
|
|
|
305
305
|
```
|
|
306
306
|
AskUserQuestion({
|
|
307
307
|
questions: [{
|
|
308
|
-
question: "
|
|
308
|
+
question: "Approve the PRD at [path]?",
|
|
309
309
|
header: "PRD Approval",
|
|
310
310
|
options: [
|
|
311
|
-
{ label: "Approve PRD (Recommended)", description: "PRD
|
|
312
|
-
{ label: "Request changes", description: "
|
|
311
|
+
{ label: "Approve PRD (Recommended)", description: "Nothing further is checked after this: approval commits the PRD to HEAD (Phase 5.5), then issue creation starts." },
|
|
312
|
+
{ label: "Request changes", description: "Describe what to change; the PRD is rewritten and comes back here. No limit on rounds." }
|
|
313
313
|
],
|
|
314
314
|
multiSelect: false
|
|
315
315
|
}]
|
|
@@ -395,18 +395,20 @@ Assign labels from the standard taxonomy:
|
|
|
395
395
|
|
|
396
396
|
### 6.3 User Review
|
|
397
397
|
|
|
398
|
-
Present the full issue structure via AskUserQuestion before creating anything:
|
|
398
|
+
Present the full issue structure via AskUserQuestion before creating anything. The table is the text that is about to be filed, so it belongs in `preview` — not in the question:
|
|
399
399
|
|
|
400
400
|
```
|
|
401
401
|
AskUserQuestion({
|
|
402
402
|
questions: [{
|
|
403
|
-
question: "
|
|
404
|
-
header: "
|
|
403
|
+
question: "Create these [N] issues from the PRD?",
|
|
404
|
+
header: "Issues",
|
|
405
405
|
options: [
|
|
406
|
-
{ label: "Create all
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
{ label: "
|
|
406
|
+
{ label: "Create all [N] (Recommended)",
|
|
407
|
+
description: "Priorities and blocked-by links come straight from the approved PRD. Cost: one API call per issue, ~1s apart.",
|
|
408
|
+
preview: "**Epic:** [title]\n\n| # | Sub-Issue | Priority | Labels | Blocked By |\n|---|----------|----------|--------|------------|\n| 1 | [title] | critical | [labels] | — |\n| 2 | [title] | high | [labels] | #1 |\n| ... | ... | ... | ... | ... |" },
|
|
409
|
+
{ label: "Adjust priorities", description: "Same [N] issues, different priority labels. Name them and this question comes back with the table updated." },
|
|
410
|
+
{ label: "Remove issues", description: "Name the ones to drop; the rest are created unchanged." },
|
|
411
|
+
{ label: "Cancel", description: "Nothing is created. The PRD stays committed, so Phase 6 can run again later." }
|
|
410
412
|
],
|
|
411
413
|
multiSelect: false
|
|
412
414
|
}]
|
|
@@ -127,7 +127,7 @@ Apply per gitlab-ops skill label taxonomy:
|
|
|
127
127
|
|
|
128
128
|
### User Review Gate
|
|
129
129
|
|
|
130
|
-
Present the full issue structure via AskUserQuestion
|
|
130
|
+
Present the full issue structure via the AskUserQuestion payload in `SKILL.md` § 6.3 — the issue table belongs in the option's `preview` field, not in the question text:
|
|
131
131
|
|
|
132
132
|
- Epic title and description
|
|
133
133
|
- Each sub-issue: title, priority, labels, dependency links
|
package/skills/plan/mode-new.md
CHANGED
|
@@ -38,7 +38,7 @@ Agent({ subagent_type: "Explore", description: "Check ecosystem for conflicts",
|
|
|
38
38
|
3. **Target audience** — Options informed by market research agent. User selects or provides custom.
|
|
39
39
|
4. **User-Story-Schicht** — "User-Story-Schicht für dieses Feature erzeugen?" Immer fragen (kein Audience-Heuristik-Gate). Drei Antwortoptionen: **Ja (Als/möchte/damit)** — klassische Persona-Story-Form; **Ja (job-story)** — job-story-Form ("When [situation], I want [motivation], so I can [outcome]"); **Nein** — byte-identisches Status-quo-Verhalten. Bei einer der beiden "Ja"-Optionen emittiert die PRD eine optionale ## User Stories Sektion (je Story ein ↳ AC-Pointer) in der gewählten Form; bei "Nein" wird die Sektion vollständig weggelassen.
|
|
40
40
|
5. **Core problem being solved** — Open-ended. Claude suggests structure if answer is vague.
|
|
41
|
-
6. **GitLab group** —
|
|
41
|
+
6. **GitLab group** — Select the GitLab host explicitly, then discover available groups dynamically. Run `ls $BASELINE_PATH/templates/` for project types, and check for a groups config in `$BASELINE_PATH/config/` or run `glab api --hostname "$GITLAB_HOST" "groups?per_page=100&min_access_level=10"` to discover GitLab groups — read each entry's `full_path` field. (`glab` has no `group` subcommand at all — invoking one exits 1 with `Unknown command "group"`.) Present findings via AskUserQuestion.
|
|
42
42
|
|
|
43
43
|
### Wave 2 — Technical Details (5 questions, dynamic per archetype)
|
|
44
44
|
|
|
@@ -134,6 +134,12 @@ Map gathered answers to script input choices:
|
|
|
134
134
|
# namespace in a separate variable — every later step addresses the project as
|
|
135
135
|
# "<group-path>/<project>", and a numeric index there silently targets nothing.
|
|
136
136
|
GROUP_PATH="$(...)" # e.g., "products" — the full_path of the chosen group
|
|
137
|
+
|
|
138
|
+
# These values identify the NEW project, not the directory in which this plan runs.
|
|
139
|
+
# Select the host with the group; do not let glab infer it from an ambient remote.
|
|
140
|
+
GITLAB_HOST="<selected GitLab hostname>"
|
|
141
|
+
PROJECT_PATH="$GROUP_PATH/$PROJECT_NAME"
|
|
142
|
+
ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$PROJECT_PATH")"
|
|
137
143
|
(
|
|
138
144
|
echo "$TYPE_CHOICE" # e.g., "1" for nextjs-saas
|
|
139
145
|
echo "$STYLE_CHOICE" # e.g., "1" for vega (only if nextjs-saas)
|
|
@@ -145,10 +151,12 @@ GROUP_PATH="$(...)" # e.g., "products" — the full_path of the chosen group
|
|
|
145
151
|
|
|
146
152
|
### Step 2: Verify success
|
|
147
153
|
|
|
148
|
-
Check exit code. Confirm
|
|
154
|
+
Check the setup script exit code. Confirm the selected path exists without fetching a full REST project object:
|
|
149
155
|
|
|
150
156
|
```bash
|
|
151
|
-
glab
|
|
157
|
+
glab api --hostname "$GITLAB_HOST" graphql \
|
|
158
|
+
-f query='query($fullPath: ID!) { project(fullPath: $fullPath) { fullPath } }' \
|
|
159
|
+
-f fullPath="$PROJECT_PATH" | jq -er '.data.project.fullPath'
|
|
152
160
|
```
|
|
153
161
|
|
|
154
162
|
### Step 3: Adjust visibility
|
|
@@ -157,27 +165,29 @@ If visibility is not `internal` (the default):
|
|
|
157
165
|
|
|
158
166
|
```bash
|
|
159
167
|
# There is no `glab repo edit`, and `glab repo update` carries no --visibility
|
|
160
|
-
# flag (its FLAGS are --archive/--defaultBranch/-d/--description).
|
|
161
|
-
#
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
# flag (its FLAGS are --archive/--defaultBranch/-d/--description). The encoded
|
|
169
|
+
# endpoint and explicit host target the new project independently of the CWD.
|
|
170
|
+
glab api --silent --hostname "$GITLAB_HOST" -X PUT \
|
|
171
|
+
"projects/${ENCODED_PROJECT_PATH}" \
|
|
172
|
+
-f visibility=private # or visibility=public
|
|
173
|
+
|
|
174
|
+
# Fetch only the scalar needed to verify the mutation, never a full REST object.
|
|
175
|
+
glab api --hostname "$GITLAB_HOST" graphql \
|
|
176
|
+
-f query='query($fullPath: ID!) { project(fullPath: $fullPath) { visibility } }' \
|
|
177
|
+
-f fullPath="$PROJECT_PATH" | jq -er '.data.project.visibility'
|
|
169
178
|
```
|
|
170
179
|
|
|
171
|
-
> The
|
|
172
|
-
>
|
|
173
|
-
>
|
|
180
|
+
> The GraphQL verification query is read-only and requests only `visibility`; the
|
|
181
|
+
> PUT's unused response is intentionally suppressed. Confirm the selected host and
|
|
182
|
+
> path before running the mutation.
|
|
174
183
|
|
|
175
184
|
For public/OSS, also configure GitHub mirror if applicable.
|
|
176
185
|
|
|
177
186
|
### Step 4: Set branch protection
|
|
178
187
|
|
|
179
188
|
```bash
|
|
180
|
-
glab api -X
|
|
189
|
+
glab api --silent --hostname "$GITLAB_HOST" -X POST \
|
|
190
|
+
"projects/${ENCODED_PROJECT_PATH}/protected_branches" \
|
|
181
191
|
-f name=main \
|
|
182
192
|
-f push_access_level=30 \
|
|
183
193
|
-f merge_access_level=30
|
|
@@ -282,7 +292,7 @@ Always use the `priority::<level>` format in VCS CLI commands, not P0/P1/P2/P3.
|
|
|
282
292
|
|
|
283
293
|
### Step 4: Present for user confirmation
|
|
284
294
|
|
|
285
|
-
Use AskUserQuestion
|
|
295
|
+
Use the AskUserQuestion payload in `SKILL.md` § 6.3 verbatim — the issue table belongs in the option's `preview` field, not in the question text:
|
|
286
296
|
|
|
287
297
|
- Epic title and description
|
|
288
298
|
- Sub-issues with: title, priority, labels, dependency links
|
|
@@ -292,11 +302,11 @@ Use AskUserQuestion to present the full issue structure:
|
|
|
292
302
|
|
|
293
303
|
```bash
|
|
294
304
|
# Create epic
|
|
295
|
-
glab issue create -R "
|
|
305
|
+
glab issue create -R "https://${GITLAB_HOST}/${PROJECT_PATH}" --title "$EPIC_TITLE" --description "$EPIC_DESC" \
|
|
296
306
|
--label "type:epic,priority::$PRIORITY" --milestone "$MILESTONE"
|
|
297
307
|
|
|
298
308
|
# Create sub-issues
|
|
299
|
-
glab issue create -R "
|
|
309
|
+
glab issue create -R "https://${GITLAB_HOST}/${PROJECT_PATH}" --title "$ISSUE_TITLE" --description "$ISSUE_DESC" \
|
|
300
310
|
--label "type:feature,priority::$PRIORITY,status:ready,area:$AREA,appetite:$APPETITE"
|
|
301
311
|
```
|
|
302
312
|
|
|
@@ -305,10 +315,12 @@ glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$ISSUE_TITLE" --descri
|
|
|
305
315
|
For issues with technical dependencies, set `blocks`/`is-blocked-by` relationships:
|
|
306
316
|
|
|
307
317
|
```bash
|
|
308
|
-
# Issue #2 is blocked by Issue #1
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
318
|
+
# Issue #2 is blocked by Issue #1 in this project. An encoded project path is
|
|
319
|
+
# valid for target_project_id, so no numeric project ID is needed.
|
|
320
|
+
glab api --silent --hostname "$GITLAB_HOST" -X POST \
|
|
321
|
+
"projects/${ENCODED_PROJECT_PATH}/issues/${ISSUE_2_IID}/links" \
|
|
322
|
+
-f target_project_id="$ENCODED_PROJECT_PATH" \
|
|
323
|
+
-f target_issue_iid="$ISSUE_1_IID" \
|
|
312
324
|
-f link_type=is_blocked_by
|
|
313
325
|
```
|
|
314
326
|
|
package/skills/plan/soul.md
CHANGED
|
@@ -69,6 +69,18 @@ The active level is `efficiency.output-level` in `~/.config/session-orchestrator
|
|
|
69
69
|
- Shape: name the alternatives you rejected and why, spell out the appetite and the scope cuts, define unfamiliar terms on first use.
|
|
70
70
|
- Escalation: `expand <topic>` — see § Escalation above.
|
|
71
71
|
|
|
72
|
+
### Register — how a sentence reads
|
|
73
|
+
|
|
74
|
+
The budgets above set *how much* you say; the register sets *how*. It is
|
|
75
|
+
defined once, in `skills/session-start/soul.md` § "Register — how a sentence
|
|
76
|
+
reads", and binds here unchanged: the frame ("write for someone who knows this
|
|
77
|
+
project but has not seen what you just saw"), the plain-words test with its
|
|
78
|
+
five worked cases, and its precedence over § "Never traded for brevity" above.
|
|
79
|
+
Read it there. It is not repeated here on purpose — the § Output Levels intro
|
|
80
|
+
sentence already exists in four copies across the four souls with nothing
|
|
81
|
+
checking their parity, and a fifth copied rule would drift the same way. A
|
|
82
|
+
pointer cannot.
|
|
83
|
+
|
|
72
84
|
### Companion dials
|
|
73
85
|
|
|
74
86
|
Same file, same lookup, same fallback-to-default rule:
|
|
@@ -243,12 +243,12 @@ For each batch (proposals sliced into groups of 4):
|
|
|
243
243
|
```
|
|
244
244
|
AskUserQuestion({
|
|
245
245
|
questions: [{
|
|
246
|
-
question: "
|
|
247
|
-
header: "
|
|
246
|
+
question: "Batch K of N — which rule proposals should be written into .claude/rules/?",
|
|
247
|
+
header: "Regeln",
|
|
248
248
|
options: [
|
|
249
249
|
{
|
|
250
250
|
label: "<slug>.md (confidence: 0.72)",
|
|
251
|
-
description: "
|
|
251
|
+
description: "From learning <learningKey>. Becomes a file under .claude/rules/ — where this repo keeps its rules. Text: <first 100 chars of rendered content>"
|
|
252
252
|
},
|
|
253
253
|
...up to 4 options per batch...
|
|
254
254
|
{
|