session-orchestrator 3.20.0 → 3.21.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/030-wave-execution.mdc +10 -8
- package/CHANGELOG.md +414 -0
- package/README.md +16 -11
- package/agents/analyst.md +1 -1
- package/agents/architect-reviewer.md +1 -1
- package/agents/code-implementer.md +4 -2
- package/agents/db-specialist.md +1 -1
- package/agents/dialectic-deriver.md +1 -1
- package/agents/docs-writer.md +1 -1
- package/agents/memory-proposal-collector.md +1 -1
- package/agents/qa-strategist.md +1 -1
- package/agents/security-reviewer.md +1 -1
- package/agents/session-reviewer.md +42 -1
- package/agents/skill-applied-judge.md +1 -1
- package/agents/test-writer.md +1 -1
- package/agents/ui-developer.md +1 -1
- package/agents/ux-evaluator.md +1 -1
- package/commands/release.md +60 -0
- package/docs/migration-v3.md +9 -6
- package/docs/persona-panel.md +3 -1
- package/docs/scope-collision-guard.md +167 -0
- package/hooks/enforce-scope.mjs +103 -3
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +11 -1
- package/hooks/on-session-end.mjs +52 -5
- package/hooks/on-stop.mjs +127 -12
- package/hooks/post-bash-write-verify.mjs +8 -32
- package/hooks/pre-task-scope-disjoint.mjs +1042 -0
- package/package.json +1 -1
- package/pi/prompts/release.md +12 -0
- package/scripts/autopilot.mjs +3 -1
- package/scripts/emit-session.mjs +42 -0
- package/scripts/export-hw-learnings.mjs +61 -2
- package/scripts/lib/autopilot/worktree-pipeline.mjs +5 -5
- package/scripts/lib/backlog-scan.mjs +106 -15
- package/scripts/lib/build-live-signals.mjs +7 -3
- package/scripts/lib/ci-status-banner.mjs +207 -23
- package/scripts/lib/git-config-drift.mjs +471 -0
- package/scripts/lib/harness-audit/categories/category6.mjs +65 -12
- package/scripts/lib/io.mjs +193 -7
- package/scripts/lib/learnings/select.mjs +157 -3
- package/scripts/lib/memory-cleanup-stamp.mjs +132 -8
- package/scripts/lib/mirror-issues-banner.mjs +266 -0
- package/scripts/lib/named-vault-resolver.mjs +105 -16
- package/scripts/lib/peer-cards/schema.mjs +6 -2
- package/scripts/lib/reconcile/writer.mjs +69 -30
- package/scripts/lib/redact-spans.mjs +89 -0
- package/scripts/lib/scope-baseline.mjs +77 -17
- package/scripts/lib/scope-gate.mjs +658 -0
- package/scripts/lib/secret-masker.mjs +262 -0
- package/scripts/lib/session-lock.mjs +34 -10
- package/scripts/lib/session-registry.mjs +9 -1
- package/scripts/lib/state-md/mission-status.mjs +21 -12
- package/scripts/lib/tmux-layout/vcs-detector.mjs +108 -4
- package/scripts/lib/validate/check-agents.mjs +77 -5
- package/scripts/lib/validate/check-commands.mjs +2 -20
- package/scripts/lib/validate/check-doc-cli-commands.mjs +514 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +18 -0
- package/scripts/lib/validate/check-owner-leakage.mjs +185 -17
- package/scripts/lib/validate/check-skills.mjs +191 -0
- package/scripts/lib/validate/check-test-git-config-target.mjs +665 -0
- package/scripts/lib/validate/check-unicode-safety.mjs +22 -2
- package/scripts/lib/validate/check-untracked-test-deps.mjs +925 -0
- package/scripts/lib/validate/check-unwired-features.mjs +219 -11
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +965 -0
- package/scripts/lib/validate/frontmatter-block.mjs +61 -0
- package/scripts/lib/validate/tier-inference.mjs +46 -8
- package/scripts/lib/vault-mirror/namespace.mjs +146 -1
- package/scripts/lib/vault-mirror/process.mjs +264 -31
- package/scripts/lib/vault-mirror/render-sessions.mjs +115 -4
- package/scripts/lib/vault-status/board-writer.mjs +300 -56
- package/scripts/lib/vault-status/narrative-mirror.mjs +119 -5
- package/scripts/lib/vcs-repo-spec.mjs +500 -19
- package/scripts/print-learnings-index.mjs +30 -3
- package/scripts/release.mjs +616 -61
- package/scripts/site-numbers.mjs +1049 -0
- package/scripts/validate-plugin.mjs +61 -0
- package/scripts/validate-wave-scope.mjs +281 -12
- package/scripts/vault-mirror.mjs +26 -1
- package/skills/_shared/monitor-patterns.md +24 -4
- package/skills/_shared/state-ownership.md +17 -0
- package/skills/claude-md-drift-check/SKILL.md +9 -1
- package/skills/debug/SKILL.md +4 -1
- package/skills/discovery/issue-templates.md +4 -4
- package/skills/discovery/probes-code.md +2 -2
- package/skills/discovery/probes-feature.md +6 -6
- package/skills/discovery/probes-infra.md +2 -2
- package/skills/discovery/probes-session.md +5 -5
- package/skills/dispatcher/SKILL.md +10 -1
- package/skills/frontmatter-guard/SKILL.md +9 -1
- package/skills/gitlab-ops/SKILL.md +49 -39
- package/skills/gitlab-portfolio/SKILL.md +10 -1
- package/skills/memory-cleanup/SKILL.md +18 -5
- package/skills/npm-publish/SKILL.md +22 -50
- package/skills/persona-panel/SKILL.md +3 -1
- package/skills/plan/mode-new.md +23 -5
- package/skills/repo-audit/SKILL.md +10 -1
- package/skills/session-end/SKILL.md +44 -2
- package/skills/session-end/metrics-collection.md +1 -1
- package/skills/session-end/session-metrics-write.md +4 -10
- package/skills/session-plan/SKILL.md +2 -2
- package/skills/session-plan/wave-template.md +1 -1
- package/skills/session-start/SKILL.md +13 -1
- package/skills/spinout/SKILL.md +5 -1
- package/skills/sunset-review/SKILL.md +11 -1
- package/skills/tmux-layout/SKILL.md +7 -2
- package/skills/vault-mirror/SKILL.md +10 -1
- package/skills/vault-sync/SKILL.md +10 -1
- package/skills/vault-sync/validator.mjs +55 -6
- package/skills/wave-executor/wave-loop.md +42 -12
- package/scripts/lib/mission-status-schema.mjs +0 -114
|
@@ -113,11 +113,11 @@ Export Status: exported/public | internal
|
|
|
113
113
|
1. List open feature/enhancement issues via the VCS CLI (syntax reference: `skills/gitlab-ops/SKILL.md` § "Common CLI Commands" — do not duplicate CLI flags here beyond what's needed to name the call):
|
|
114
114
|
```bash
|
|
115
115
|
# GitLab
|
|
116
|
-
glab issue list --label "feature" --per-page 100
|
|
117
|
-
glab issue list --label "enhancement" --per-page 100
|
|
116
|
+
glab issue list -R <OWNER>/<REPO> --label "feature" --per-page 100
|
|
117
|
+
glab issue list -R <OWNER>/<REPO> --label "enhancement" --per-page 100
|
|
118
118
|
# GitHub
|
|
119
|
-
gh issue list --label "feature" --limit 100
|
|
120
|
-
gh issue list --label "enhancement" --limit 100
|
|
119
|
+
gh issue list -R <OWNER>/<REPO> --label "feature" --limit 100
|
|
120
|
+
gh issue list -R <OWNER>/<REPO> --label "enhancement" --limit 100
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
2. Extract theme keywords from each issue's title (and first paragraph of body where available): lowercase, strip stop-words, tokenize on non-alphanumeric boundaries. Group issues that share two or more significant keywords (e.g. "export", "csv", "invoice") into a candidate cluster.
|
|
@@ -125,10 +125,10 @@ gh issue list --label "enhancement" --limit 100
|
|
|
125
125
|
3. For each candidate cluster with 3 or more issues, check whether ANY member issue is already linked to an epic (`epic` label, a GitLab Epic relationship, or an in-body reference such as `part of #<epic-iid>` / `Epic: #<epic-iid>`):
|
|
126
126
|
```bash
|
|
127
127
|
# GitLab -- inspect labels + description for epic linkage
|
|
128
|
-
glab issue view <IID>
|
|
128
|
+
glab issue view -R <OWNER>/<REPO> <IID>
|
|
129
129
|
Grep pattern: (^Labels:.*\bepic\b|part of #|Epic:\s*#)
|
|
130
130
|
# GitHub -- same check against issue body/labels
|
|
131
|
-
gh issue view <NUMBER>
|
|
131
|
+
gh issue view -R <OWNER>/<REPO> <NUMBER>
|
|
132
132
|
Grep pattern: (^labels:.*\bepic\b|part of #|Epic:\s*#)
|
|
133
133
|
```
|
|
134
134
|
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
# GitLab: query recent pipeline status
|
|
13
|
-
glab pipeline list --per-page 10
|
|
13
|
+
glab pipeline list -R <OWNER>/<REPO> --per-page 10
|
|
14
14
|
|
|
15
15
|
# GitHub: query recent workflow runs
|
|
16
|
-
gh run list --limit 10
|
|
16
|
+
gh run list -R <OWNER>/<REPO> --limit 10
|
|
17
17
|
|
|
18
18
|
# Parse output for:
|
|
19
19
|
# - Repeated failures (same pipeline failing 3+ times in a row)
|
|
@@ -55,9 +55,9 @@ Grep pattern: <claimed_addition>
|
|
|
55
55
|
git show <commit_hash> -- <relevant_files>
|
|
56
56
|
|
|
57
57
|
# "Closes #N" -> verify acceptance criteria from issue #N are met
|
|
58
|
-
gh issue view <N> --json body -q '.body'
|
|
58
|
+
gh issue view -R <OWNER>/<REPO> <N> --json body -q '.body'
|
|
59
59
|
# or
|
|
60
|
-
glab issue view <N>
|
|
60
|
+
glab issue view -R <OWNER>/<REPO> <N>
|
|
61
61
|
|
|
62
62
|
# Step 3: Cross-reference claims against actual changes
|
|
63
63
|
git diff <commit_hash>~1..<commit_hash>
|
|
@@ -83,10 +83,10 @@ Evidence: <what was found or not found>
|
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
85
|
# GitLab: list open issues sorted by last update
|
|
86
|
-
glab issue list --per-page 100 | head -50
|
|
86
|
+
glab issue list -R <OWNER>/<REPO> --per-page 100 | head -50
|
|
87
87
|
|
|
88
88
|
# GitHub: list open issues sorted by last update
|
|
89
|
-
gh issue list --limit 100 --json number,title,labels,updatedAt,assignees --jq '.[] | select(.updatedAt < "<30_days_ago_iso>")'
|
|
89
|
+
gh issue list -R <OWNER>/<REPO> --limit 100 --json number,title,labels,updatedAt,assignees --jq '.[] | select(.updatedAt < "<30_days_ago_iso>")'
|
|
90
90
|
|
|
91
91
|
# Flag:
|
|
92
92
|
# - Issues with no activity in stale-issue-days (default: 30 days)
|
|
@@ -131,7 +131,7 @@ for issue in issues:
|
|
|
131
131
|
"
|
|
132
132
|
|
|
133
133
|
# GitHub: fetch issue bodies and parse cross-references
|
|
134
|
-
gh issue list --limit 100 --json number,body --jq '.[] | {number, body}' | python3 -c "
|
|
134
|
+
gh issue list -R <OWNER>/<REPO> --limit 100 --json number,body --jq '.[] | {number, body}' | python3 -c "
|
|
135
135
|
import json, sys, re
|
|
136
136
|
for line in sys.stdin:
|
|
137
137
|
issue = json.loads(line)
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dispatcher
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Use when you want the orchestrator to pick the next repo to work on across your whole portfolio — it
|
|
5
|
+
enumerates candidate repos below the confinement root, resolves free/busy from each repo's session.lock
|
|
6
|
+
lease, ranks the FREE ones by backlog priority × staleness × readiness, recommends the single most
|
|
7
|
+
worthwhile one via AskUserQuestion, atomically claims it, and routes you to the chosen entry command.
|
|
8
|
+
Triggers: "what should I work on next", "dispatch me to a repo", "pick the next project", "run
|
|
9
|
+
/dispatcher". <example>Context: operator finished a session and wants the next-best repo across the
|
|
10
|
+
portfolio. user: "/dispatcher" assistant: "Ranked 18 free repos — top recommendation: Pencil-Designs
|
|
11
|
+
(score 4.50, 90d stale). Confirm via the picker, I'll claim its lease atomically, then route you to
|
|
12
|
+
/session deep."</example>
|
|
4
13
|
model: sonnet
|
|
5
14
|
---
|
|
6
15
|
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: frontmatter-guard
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Injects the canonical vault frontmatter schema snippet into agent prompts before any vault-write task,
|
|
5
|
+
preventing malformed YAML frontmatter in Obsidian notes. <example>Context: wave-executor is about to
|
|
6
|
+
dispatch a vault-mirror agent that writes learning notes under ~/Projects/vault/40-learnings/. user:
|
|
7
|
+
"dispatch vault-write agent" assistant: "Injecting frontmatter-guard snippet into agent prompt (vault
|
|
8
|
+
scope detected). Required fields: id, type, created, updated. Enum type:
|
|
9
|
+
note|daily|project|person|reference|idea|learning|session." <commentary>The wave-executor pre-dispatch
|
|
10
|
+
hook calls detectVaultTaskScope() — the fileScope contains /Projects/vault/40-learnings/ so the guard
|
|
11
|
+
triggers and the snippet is prepended to the agent system prompt.</commentary></example>
|
|
4
12
|
model: inherit
|
|
5
13
|
---
|
|
6
14
|
|
|
@@ -6,7 +6,15 @@ model: haiku
|
|
|
6
6
|
model-preference: sonnet
|
|
7
7
|
model-preference-codex: gpt-5.4-mini
|
|
8
8
|
model-preference-cursor: claude-sonnet-4-6
|
|
9
|
-
description:
|
|
9
|
+
description: >
|
|
10
|
+
Use this skill when performing VCS operations on GitLab or GitHub repositories — creating, updating, or
|
|
11
|
+
closing issues and MRs, applying label taxonomy, running `glab`/`gh` CLI commands, or resolving project
|
|
12
|
+
IDs dynamically. Acts as the single source of truth for CLI command syntax and label conventions;
|
|
13
|
+
consuming skills reference this rather than duplicating logic. Triggers: "create a GitLab issue", "list
|
|
14
|
+
open MRs", "apply priority label", "how do I resolve the project ID", "what's the carryover issue
|
|
15
|
+
template". <example>Context: session-end needs to file a carryover issue for an incomplete task. user:
|
|
16
|
+
"/close" assistant: "Creating carryover issue via glab with the Carryover Template from gitlab-ops —
|
|
17
|
+
labels: carryover, priority::high."</example>
|
|
10
18
|
---
|
|
11
19
|
|
|
12
20
|
# VCS Operations Reference
|
|
@@ -57,9 +65,9 @@ Never hardcode project IDs. Resolve them at runtime — and re-resolve live each
|
|
|
57
65
|
|
|
58
66
|
```bash
|
|
59
67
|
# GitLab — get numeric project ID
|
|
60
|
-
glab repo view --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])"
|
|
68
|
+
glab repo view -R <OWNER>/<REPO> --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])"
|
|
61
69
|
|
|
62
|
-
# GitHub — get owner/name identifier
|
|
70
|
+
# GitHub — get owner/name identifier (gh repo takes the repo POSITIONALLY; it rejects -R)
|
|
63
71
|
gh repo view --json nameWithOwner -q '.nameWithOwner'
|
|
64
72
|
```
|
|
65
73
|
|
|
@@ -153,33 +161,35 @@ GitHub has no native issue-blocking relation at all — the body-ordering-note f
|
|
|
153
161
|
|
|
154
162
|
## Common CLI Commands
|
|
155
163
|
|
|
164
|
+
**Directive — consult this only for a command NOT listed below; every example here already complies.** Each repo-scoped `glab`/`gh` invocation carries `-R <OWNER>/<REPO>` (`glab` also accepts `GROUP/SUBGROUP/REPO` or a full remote URL — `resolveRepoSpec()` in `scripts/lib/vcs-repo-spec.mjs` produces the right spec per platform); without the flag the target is whatever the ambient cwd remote happens to be, which is the wrong project in a sibling worktree, an `/autopilot` child, or a fork. Exactly four exceptions, each probed against the binaries: `glab api`/`gh api` (no `--repo` exists — pin the host with `--hostname` from `resolveRepoHost()` instead), `gh repo <*>` (rejects `-R`; takes the repository positionally), a `glab repo` call that already names the repository positionally, and — conditionally, not subcommand-wide — `gh pr checks|view|diff|ready|merge|comment`, where `-R` is legal ONLY alongside the `<number>|<url>|<branch>` positional: `gh pr checks -R <OWNER>/<REPO> <BRANCH>` carries the flag, while a positional-less `gh pr checks -R <OWNER>/<REPO> --watch` exits 1 with `argument required when using the` `--repo` `flag` — so name the PR or drop the flag, and never derive this from `--help`, which lists `-R` under INHERITED FLAGS with no such qualifier.
|
|
165
|
+
|
|
156
166
|
### GitLab (glab)
|
|
157
167
|
|
|
158
168
|
```bash
|
|
159
169
|
# Issues
|
|
160
|
-
glab issue list --per-page 50
|
|
161
|
-
glab issue list --label "status:ready" --per-page 10
|
|
162
|
-
glab issue list --label "priority::high" --per-page 10
|
|
163
|
-
glab issue list --closed --per-page 10
|
|
164
|
-
glab issue view <IID>
|
|
165
|
-
glab issue view <IID> --comments
|
|
166
|
-
glab issue create --title "title" --label "priority::high,status:ready"
|
|
167
|
-
glab issue update <IID> --label "status:in-progress"
|
|
168
|
-
glab issue close <IID>
|
|
169
|
-
glab issue note <IID> -m "Comment text"
|
|
170
|
+
glab issue list -R <OWNER>/<REPO> --per-page 50 # All open issues
|
|
171
|
+
glab issue list -R <OWNER>/<REPO> --label "status:ready" --per-page 10 # Ready to work on
|
|
172
|
+
glab issue list -R <OWNER>/<REPO> --label "priority::high" --per-page 10 # High priority
|
|
173
|
+
glab issue list -R <OWNER>/<REPO> --closed --per-page 10 # Recently closed
|
|
174
|
+
glab issue view -R <OWNER>/<REPO> <IID> # View issue details
|
|
175
|
+
glab issue view -R <OWNER>/<REPO> <IID> --comments # With comments
|
|
176
|
+
glab issue create -R <OWNER>/<REPO> --title "title" --label "priority::high,status:ready"
|
|
177
|
+
glab issue update -R <OWNER>/<REPO> <IID> --label "status:in-progress" # WARNING: --label REPLACES the full set — see caveat below
|
|
178
|
+
glab issue close -R <OWNER>/<REPO> <IID> # then VERIFY: re-read the issue; it must show state=closed
|
|
179
|
+
glab issue note -R <OWNER>/<REPO> <IID> -m "Comment text" # Add comment
|
|
170
180
|
|
|
171
181
|
# MRs
|
|
172
|
-
glab mr list
|
|
173
|
-
glab mr create --fill --draft
|
|
174
|
-
glab mr merge <MR_IID>
|
|
182
|
+
glab mr list -R <OWNER>/<REPO> # Open MRs
|
|
183
|
+
glab mr create -R <OWNER>/<REPO> --fill --draft # Create draft MR
|
|
184
|
+
glab mr merge -R <OWNER>/<REPO> <MR_IID> # Merge MR
|
|
175
185
|
|
|
176
186
|
# Pipelines
|
|
177
|
-
glab pipeline list --per-page 5
|
|
178
|
-
glab pipeline status <ID>
|
|
187
|
+
glab pipeline list -R <OWNER>/<REPO> --per-page 5 # Recent pipelines
|
|
188
|
+
glab pipeline status -R <OWNER>/<REPO> <ID> # Pipeline details
|
|
179
189
|
|
|
180
|
-
# API (
|
|
181
|
-
glab api "projects/$(glab repo view --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")/issues?state=opened&per_page=50"
|
|
182
|
-
glab api "projects/$(glab repo view --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")/milestones?state=active"
|
|
190
|
+
# API (no --repo exists here — the endpoint path IS the target; pin the host with --hostname)
|
|
191
|
+
glab api "projects/$(glab repo view -R <OWNER>/<REPO> --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")/issues?state=opened&per_page=50"
|
|
192
|
+
glab api "projects/$(glab repo view -R <OWNER>/<REPO> --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")/milestones?state=active"
|
|
183
193
|
```
|
|
184
194
|
|
|
185
195
|
**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`.
|
|
@@ -194,27 +204,27 @@ glab api "projects/$(glab repo view --output json | python3 -c "import json,sys;
|
|
|
194
204
|
|
|
195
205
|
```bash
|
|
196
206
|
# Issues
|
|
197
|
-
gh issue list --limit 50
|
|
198
|
-
gh issue list --label "status:ready" --limit 10
|
|
199
|
-
gh issue list --label "priority::high" --limit 10
|
|
200
|
-
gh issue list --state closed --limit 10
|
|
201
|
-
gh issue view <NUMBER>
|
|
202
|
-
gh issue view <NUMBER> --comments
|
|
203
|
-
gh issue create --title "title" --label "priority::high,status:ready"
|
|
204
|
-
gh issue edit <NUMBER> --add-label "status:in-progress"
|
|
205
|
-
gh issue close <NUMBER>
|
|
206
|
-
gh issue comment <NUMBER> --body "Comment text"
|
|
207
|
+
gh issue list -R <OWNER>/<REPO> --limit 50 # All open issues
|
|
208
|
+
gh issue list -R <OWNER>/<REPO> --label "status:ready" --limit 10 # Ready to work on
|
|
209
|
+
gh issue list -R <OWNER>/<REPO> --label "priority::high" --limit 10 # High priority
|
|
210
|
+
gh issue list -R <OWNER>/<REPO> --state closed --limit 10 # Recently closed
|
|
211
|
+
gh issue view -R <OWNER>/<REPO> <NUMBER> # View issue details
|
|
212
|
+
gh issue view -R <OWNER>/<REPO> <NUMBER> --comments # With comments
|
|
213
|
+
gh issue create -R <OWNER>/<REPO> --title "title" --label "priority::high,status:ready"
|
|
214
|
+
gh issue edit -R <OWNER>/<REPO> <NUMBER> --add-label "status:in-progress"
|
|
215
|
+
gh issue close -R <OWNER>/<REPO> <NUMBER>
|
|
216
|
+
gh issue comment -R <OWNER>/<REPO> <NUMBER> --body "Comment text" # Add comment
|
|
207
217
|
|
|
208
218
|
# PRs
|
|
209
|
-
gh pr list --state open
|
|
210
|
-
gh pr create --fill --draft
|
|
211
|
-
gh pr merge <NUMBER>
|
|
219
|
+
gh pr list -R <OWNER>/<REPO> --state open # Open PRs
|
|
220
|
+
gh pr create -R <OWNER>/<REPO> --fill --draft # Create draft PR
|
|
221
|
+
gh pr merge -R <OWNER>/<REPO> <NUMBER> # Merge PR
|
|
212
222
|
|
|
213
223
|
# Workflows (CI equivalent)
|
|
214
|
-
gh run list --limit 5
|
|
215
|
-
gh run view <RUN_ID>
|
|
224
|
+
gh run list -R <OWNER>/<REPO> --limit 5 # Recent workflow runs
|
|
225
|
+
gh run view -R <OWNER>/<REPO> <RUN_ID> # Run details
|
|
216
226
|
|
|
217
|
-
# API
|
|
227
|
+
# API (no --repo exists here — the endpoint path IS the target; pin the host with --hostname)
|
|
218
228
|
gh api "repos/{owner}/{repo}/issues?state=open&per_page=50"
|
|
219
229
|
gh api "repos/{owner}/{repo}/milestones?state=open"
|
|
220
230
|
```
|
|
@@ -367,8 +377,8 @@ Read .gitlab/merge_request_templates/Default.md
|
|
|
367
377
|
Read .github/PULL_REQUEST_TEMPLATE.md
|
|
368
378
|
|
|
369
379
|
# 2. Then create — hook now passes
|
|
370
|
-
glab mr create --title "..." --description "..."
|
|
371
|
-
gh pr create --title "..." --body "..."
|
|
380
|
+
glab mr create -R <OWNER>/<REPO> --title "..." --description "..."
|
|
381
|
+
gh pr create -R <OWNER>/<REPO> --title "..." --body "..."
|
|
372
382
|
```
|
|
373
383
|
|
|
374
384
|
### Cross-References
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gitlab-portfolio
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Use when you need a single-pane cross-repo health view across all vault-registered GitLab and GitHub
|
|
5
|
+
projects. Discovers repos from `_overview.md` frontmatter in `<vault>/01-projects/*/`, aggregates open
|
|
6
|
+
issues, MRs, critical labels, and stale signals via parallel `glab`/`gh` calls, then writes an
|
|
7
|
+
idempotent `_PORTFOLIO.md` dashboard. Runs automatically at session-start Phase 2 when
|
|
8
|
+
`gitlab-portfolio.enabled=true`. Triggers: "show portfolio status", "refresh the portfolio dashboard",
|
|
9
|
+
"which repos have critical issues", "run /portfolio". <example>Context: session-start,
|
|
10
|
+
gitlab-portfolio.enabled=true, vault has 5 registered repos. user: "/session deep" assistant:
|
|
11
|
+
"Portfolio: 3 critical issues across 2 repos — run /portfolio for details. Dashboard written to
|
|
12
|
+
vault/01-projects/_PORTFOLIO.md."</example>
|
|
4
13
|
model: sonnet
|
|
5
14
|
---
|
|
6
15
|
|
|
@@ -296,11 +296,24 @@ After completing all four phases, report:
|
|
|
296
296
|
|
|
297
297
|
This advances the auto-dream cadence marker (`readDreamSignals` → `lastCleanupAt` in `scripts/lib/auto-dream.mjs`) so `shouldDispatchAutoDream` does not fire a false nudge on the next session.
|
|
298
298
|
|
|
299
|
-
**Signalling contract
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
299
|
+
**Signalling contract — emit the event, do not rely on remembering.**
|
|
300
|
+
|
|
301
|
+
As the LAST step of every completed run — dry-run, apply-pending, or healthy no-op alike — emit the completion event. This is mandatory and it is the whole mechanism; there is no second, prose-only path that also works:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
node scripts/emit-event.mjs \
|
|
305
|
+
--type orchestrator.memory.cleanup_completed \
|
|
306
|
+
--payload "{\"semantic_session_id\":\"<the session: value from STATE.md frontmatter>\",\"mode\":\"<dry-run|apply-pending|no-op>\"}"
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
`scripts/emit-session.mjs` then DERIVES `memory_cleanup_at` from that event at session-close time via `deriveMemoryCleanupSignal()` (`scripts/lib/memory-cleanup-stamp.mjs`), matching events whose `timestamp` falls inside the session's own `[started_at, completed_at]` window. Nothing downstream depends on the coordinator recalling that a cleanup happened.
|
|
310
|
+
|
|
311
|
+
- **Do NOT distinguish "applied changes" from "healthy no-op"** — both count as a run, so both emit. Put the distinction in `mode`, never in whether you emit.
|
|
312
|
+
- **Do NOT hand-append to `events.jsonl`.** Route through `emit-event.mjs` → `emitEvent()`; hand-rolled appenders drift from the canonical record shape (the `stop` vs `orchestrator.session.stopped` divergence, #609).
|
|
313
|
+
- **`semantic_session_id` is the semantic id** (`main-2026-08-17-session-1`), not the UUID — `sessions.jsonl` `session_id` lives in that same space, and the matcher compares against it. Omitting the field is tolerated (the event is then claimed on the time window alone), but supplying it is what makes attribution exact when two sessions overlap.
|
|
314
|
+
- **An explicit `memory_cleanup_at` already on the record WINS** over derivation and is never overwritten. That path exists for backfills and tests, not for normal operation.
|
|
315
|
+
|
|
316
|
+
**Why this is mechanical and not a prose instruction:** it used to be one. On 2026-08-14 a `/memory-cleanup` ran and produced a documented yield, the coordinator did not execute the prose step, and all three session records of that day carried `memory_cleanup_at: null` — so the session-start banner reported "last cleanup 29 days ago" while the operator's own notes said 3. `stampMemoryCleanup()` had zero production callers at the time; every reference to it was an instruction asking an LLM to remember. Same failure class as the STATE.md write-race that Epic #583 replaced with a lock: Disziplin statt Mechanik.
|
|
304
317
|
|
|
305
318
|
## Anti-Patterns
|
|
306
319
|
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
name: npm-publish
|
|
3
3
|
user-invocable: true
|
|
4
4
|
model: sonnet
|
|
5
|
-
description: Use when publishing this package to npm — a version release (npm publish), verifying the registry/pi.dev listing, or diagnosing npm auth failures (E403 2FA/token errors). Token-based flow via NPM_TOKEN in .env.local with a temp userconfig, leakage
|
|
5
|
+
description: Use when publishing this package to npm — a version release (npm publish), verifying the registry/pi.dev listing, or diagnosing npm auth failures (E403 2FA/token errors). Token-based flow via NPM_TOKEN in .env.local with a temp userconfig, the leakage gate before every publish, post-publish verification and marker/badge upkeep. Trigger on "publish to npm", "npm release", "E403 publish error".
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# npm-publish —
|
|
8
|
+
# npm-publish — token auth, and the calls the script cannot make
|
|
9
9
|
|
|
10
|
-
>
|
|
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-publish, push to both remotes, live-site poll. This skill does not restate it.
|
|
11
|
+
>
|
|
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.
|
|
11
13
|
|
|
12
14
|
## Why this skill exists
|
|
13
15
|
|
|
@@ -24,60 +26,20 @@ Create at https://www.npmjs.com/settings/<user>/tokens → Generate New Token
|
|
|
24
26
|
|
|
25
27
|
## Auth resolution order
|
|
26
28
|
|
|
27
|
-
1. `NPM_TOKEN` in `.env.local` at the repo root (gitignored — verify with `git check-ignore .env.local` before writing; also confirm no `.env` pattern in the `files` whitelist of package.json).
|
|
29
|
+
1. `NPM_TOKEN` in `.env.local` at the repo root (gitignored — verify with `git check-ignore .env.local` before writing; also confirm no `.env` pattern in the `files` whitelist of package.json). `scripts/release.mjs` refuses to read the token if that ignore check fails.
|
|
28
30
|
2. Interactive fallback: operator runs `npm publish --access public` in a real terminal (only works when account 2FA is enrolled — OTP prompt appears).
|
|
29
31
|
|
|
30
32
|
**Never** put the token in the tracked `.npmrc` (it holds `ignore-scripts=true` per SEC-020 and is committed), never persist it into `~/.npmrc`, never echo it into logs.
|
|
31
33
|
|
|
32
|
-
##
|
|
34
|
+
## The three judgement calls
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
version-surface sync this skill previously left to operator memory (the gap that let v3.18.0
|
|
36
|
-
ship tagged but unpublished):
|
|
36
|
+
The script gates mechanics. These three are yours, and it will not make them for you.
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
node scripts/release.mjs --set-version X.Y.Z # rewrite all 12 version literals (10 files) + codex cachebuster + lock sync
|
|
40
|
-
# … author CHANGELOG entry + README highlights (enforced by --check) …
|
|
41
|
-
node scripts/release.mjs --check # preflight: surfaces, CHANGELOG, tag/registry collision, CI green, leakage gate
|
|
42
|
-
node scripts/release.mjs --publish # token publish → registry verify → tag AFTER publish → push origin+github
|
|
43
|
-
```
|
|
38
|
+
**1. Which version is the right one.** Semver per `.claude/rules/development.md` § Package Lifecycle & Versioning: patch = fixes/docs/internal refactor; minor = additive and backwards-compatible; major = removed or renamed exports, or changed runtime behaviour — and a major never merges without a migration guide and a `BREAKING CHANGE:` footer. The script validates the *shape* `X.Y.Z` and nothing about whether the number matches the diff. Read the CHANGELOG entry you just wrote and ask whether a consumer pinning `^` would be broken by it; if yes, the bump is a major regardless of how small the diff looks.
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
below remains as the fallback and as documentation of what the script does.
|
|
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.
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
# 1. Pre-flight (first publish: expect E404 = name free; upgrade: expect the previous version)
|
|
52
|
-
npm view session-orchestrator version
|
|
53
|
-
|
|
54
|
-
# 2. Leakage gate — every grep MUST print 0 (from docs/distribution/npm-publish-checklist.md)
|
|
55
|
-
npm pack --dry-run 2>&1 | grep -cE "npm notice.* tests/"
|
|
56
|
-
npm pack --dry-run 2>&1 | grep -c "npm notice.*\.orchestrator/"
|
|
57
|
-
npm pack --dry-run 2>&1 | grep -cE "npm notice.*[[:space:]]\.claude/"
|
|
58
|
-
npm pack --dry-run 2>&1 | grep -c "npm notice.*\.github/"
|
|
59
|
-
npm pack --dry-run 2>&1 | grep -c "node_modules"
|
|
60
|
-
npm pack --dry-run 2>&1 | grep -ci "\.env"
|
|
61
|
-
npm pack --dry-run 2>&1 | grep -ci "owner\.yaml"
|
|
62
|
-
|
|
63
|
-
# 3. Publish via temp userconfig (never a persistent npmrc)
|
|
64
|
-
NPM_TOKEN=$(grep '^NPM_TOKEN=' .env.local | cut -d= -f2-)
|
|
65
|
-
TMPRC=$(mktemp) && printf '//registry.npmjs.org/:_authToken=%s\n' "$NPM_TOKEN" > "$TMPRC" && chmod 600 "$TMPRC"
|
|
66
|
-
npm publish --access public --userconfig "$TMPRC"; rm "$TMPRC"
|
|
67
|
-
|
|
68
|
-
# 4. Verify
|
|
69
|
-
npm view session-orchestrator version # must print the new version
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Success marker: `+ session-orchestrator@<version>` on the publish output.
|
|
73
|
-
|
|
74
|
-
## Post-publish checklist
|
|
75
|
-
|
|
76
|
-
1. **Verify registry**: `npm view session-orchestrator version dist.unpackedSize keywords` — `pi-package` keyword must be present.
|
|
77
|
-
2. **pi.dev gallery**: indexing is asynchronous — check https://pi.dev/packages later; do not block on it.
|
|
78
|
-
3. **Marker upkeep** (first publish only — done in v3.16.0): README install matrix + npm badge, `site/index.html` install section, `docs/pi-setup.md` availability paragraph.
|
|
79
|
-
4. **Rotate/delete the token** at https://www.npmjs.com/settings/<user>/tokens once the release is done — especially if the token value ever transited chat, a screenshot, or any log. A token pasted into a conversation is burned: rotate immediately after use.
|
|
80
|
-
5. Update the release issue / CHANGELOG if the publish was part of a tracked release.
|
|
42
|
+
**3. When to abort instead of repair.** Abort — do not patch forward — when the failure is upstream of the publish: a red preflight row, a lagging `github` mirror, CI not green on the exact commit, a dead token. These are cheap to fix and re-run from the top. Repair-in-place is only ever appropriate *after* a verified publish, where the version is already immutable: a missing GitHub release or a lagging site deploy can be reconciled, because npm already has the correct artifact. The dividing line is whether the registry has accepted the tarball — before that point, restart; after it, reconcile. `commands/release.md` § Abort criteria is the operative list.
|
|
81
43
|
|
|
82
44
|
## Failure-mode table
|
|
83
45
|
|
|
@@ -85,13 +47,23 @@ Success marker: `+ session-orchestrator@<version>` on the publish output.
|
|
|
85
47
|
|---|---|---|
|
|
86
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 |
|
|
87
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
|
+
| `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 |
|
|
88
51
|
| `E404` on `npm view` after publish | Registry propagation (rare, seconds) or publish actually failed | Re-check the publish output for `+ <name>@<version>` |
|
|
89
52
|
| `ENEEDAUTH` | No login/token at all | Token flow above, or `npm login` |
|
|
90
53
|
| OTP prompt appears but flow is non-interactive (`!`-prefix, script) | No TTY for the prompt | Use the token flow, or a real terminal |
|
|
91
54
|
|
|
55
|
+
## Post-publish — the human half
|
|
56
|
+
|
|
57
|
+
`--publish` verifies the registry and polls the live site itself, and prints the rest. What still needs a person:
|
|
58
|
+
|
|
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
|
+
2. **pi.dev gallery**: indexing is asynchronous — check https://pi.dev/packages later; do not block on it.
|
|
61
|
+
3. **Marker upkeep** on a first publish only (done in v3.16.0): README install matrix + npm badge, `site/index.html` install section, `docs/pi-setup.md` availability paragraph.
|
|
62
|
+
4. Update the release issue if the publish was part of tracked work.
|
|
63
|
+
|
|
92
64
|
## Security invariants
|
|
93
65
|
|
|
94
66
|
- `.env.local` is gitignored AND absent from the npm `files` whitelist — verify both before writing a token into it.
|
|
95
|
-
- Temp userconfig: `chmod 600`, deleted immediately after publish.
|
|
67
|
+
- Temp userconfig: `chmod 600`, deleted in a `finally` block immediately after publish.
|
|
96
68
|
- The leakage gate runs before EVERY publish, not only the first.
|
|
97
69
|
- npm's own recommendation for unattended CI/CD is **Trusted Publishing** (OIDC) — evaluate it if publishing ever moves into CI (ref: https://docs.npmjs.com/about-access-tokens).
|
|
@@ -40,7 +40,9 @@ catalog rather than referencing the plugin copy in place.
|
|
|
40
40
|
Install:
|
|
41
41
|
```bash
|
|
42
42
|
mkdir -p .claude/personas
|
|
43
|
-
|
|
43
|
+
# Claude Code has no `plugin dir` subcommand — resolve the install path from the cache.
|
|
44
|
+
SO_DIR="$(dirname "$(find ~/.claude/plugins/cache -path '*session-orchestrator*' -name package.json 2>/dev/null | head -1)")"
|
|
45
|
+
cp "$SO_DIR/skills/persona-panel/presets/"*.md .claude/personas/
|
|
44
46
|
```
|
|
45
47
|
|
|
46
48
|
## Phase 0: Bootstrap Gate
|
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** — Discover available groups dynamically. Run `ls $BASELINE_PATH/templates/` for project types, and check for a groups config in `$BASELINE_PATH/config/` or
|
|
41
|
+
6. **GitLab group** — 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 "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
|
|
|
@@ -129,6 +129,11 @@ Map gathered answers to script input choices:
|
|
|
129
129
|
# 4. Map user's selected style name → numeric choice for STYLE_CHOICE (if applicable)
|
|
130
130
|
# 5. Map user's selected group name → numeric choice for GROUP_CHOICE
|
|
131
131
|
# Do NOT hardcode numeric mappings — they must be derived from the script.
|
|
132
|
+
#
|
|
133
|
+
# GROUP_CHOICE is a MENU INDEX, never a namespace. Keep the group's real
|
|
134
|
+
# namespace in a separate variable — every later step addresses the project as
|
|
135
|
+
# "<group-path>/<project>", and a numeric index there silently targets nothing.
|
|
136
|
+
GROUP_PATH="$(...)" # e.g., "products" — the full_path of the chosen group
|
|
132
137
|
(
|
|
133
138
|
echo "$TYPE_CHOICE" # e.g., "1" for nextjs-saas
|
|
134
139
|
echo "$STYLE_CHOICE" # e.g., "1" for vega (only if nextjs-saas)
|
|
@@ -143,7 +148,7 @@ Map gathered answers to script input choices:
|
|
|
143
148
|
Check exit code. Confirm repo exists:
|
|
144
149
|
|
|
145
150
|
```bash
|
|
146
|
-
glab repo view $
|
|
151
|
+
glab repo view "$GROUP_PATH/$PROJECT_NAME"
|
|
147
152
|
```
|
|
148
153
|
|
|
149
154
|
### Step 3: Adjust visibility
|
|
@@ -151,9 +156,22 @@ glab repo view $GROUP/$PROJECT_NAME
|
|
|
151
156
|
If visibility is not `internal` (the default):
|
|
152
157
|
|
|
153
158
|
```bash
|
|
154
|
-
glab repo edit
|
|
159
|
+
# There is no `glab repo edit`, and `glab repo update` carries no --visibility
|
|
160
|
+
# flag (its FLAGS are --archive/--defaultBranch/-d/--description). Go through the
|
|
161
|
+
# API, addressing the project by its URL-encoded path — `projects/:id` resolves
|
|
162
|
+
# from the CWD remote, which is the wrong project right after scaffolding.
|
|
163
|
+
ENCODED="${GROUP_PATH}%2F${PROJECT_NAME}"
|
|
164
|
+
glab api -X PUT "projects/${ENCODED}" -f visibility=private # or visibility=public
|
|
165
|
+
|
|
166
|
+
# Verify (this GET is the read-only proof the PUT landed). Note `glab api` has
|
|
167
|
+
# no --jq flag — that is `gh api`'s. Pipe to jq instead.
|
|
168
|
+
glab api "projects/${ENCODED}" | jq -r '.visibility'
|
|
155
169
|
```
|
|
156
170
|
|
|
171
|
+
> The GET path above is verified against glab 1.91.0; the PUT is the documented
|
|
172
|
+
> GitLab API shape but was **not** executed during authoring (write operations
|
|
173
|
+
> were out of scope). Confirm with the GET before relying on it.
|
|
174
|
+
|
|
157
175
|
For public/OSS, also configure GitHub mirror if applicable.
|
|
158
176
|
|
|
159
177
|
### Step 4: Set branch protection
|
|
@@ -274,11 +292,11 @@ Use AskUserQuestion to present the full issue structure:
|
|
|
274
292
|
|
|
275
293
|
```bash
|
|
276
294
|
# Create epic
|
|
277
|
-
glab issue create --title "$EPIC_TITLE" --description "$EPIC_DESC" \
|
|
295
|
+
glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$EPIC_TITLE" --description "$EPIC_DESC" \
|
|
278
296
|
--label "type:epic,priority::$PRIORITY" --milestone "$MILESTONE"
|
|
279
297
|
|
|
280
298
|
# Create sub-issues
|
|
281
|
-
glab issue create --title "$ISSUE_TITLE" --description "$ISSUE_DESC" \
|
|
299
|
+
glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$ISSUE_TITLE" --description "$ISSUE_DESC" \
|
|
282
300
|
--label "type:feature,priority::$PRIORITY,status:ready,area:$AREA,appetite:$APPETITE"
|
|
283
301
|
```
|
|
284
302
|
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: repo-audit
|
|
3
|
-
description:
|
|
3
|
+
description: >
|
|
4
|
+
Use this skill when the user wants to audit a repository for baseline compliance, check code quality,
|
|
5
|
+
security posture, CI/CD setup, testing, documentation, and ecosystem configuration. Runs 9 checklist
|
|
6
|
+
categories and emits a Markdown report plus JSON sidecar at
|
|
7
|
+
.orchestrator/metrics/repo-audit-<timestamp>.json. <example>Context: User is in a project repo and wants
|
|
8
|
+
a baseline compliance check. user: "/repo-audit" assistant: "Running repo-audit across 9 categories —
|
|
9
|
+
Configuration, Code Quality, Git Hygiene, CI/CD, Testing, Security, Documentation, Clank Integration
|
|
10
|
+
(optional), and MCP Configuration. Will produce a Markdown checklist report and JSON sidecar."
|
|
11
|
+
<commentary>The user wants a compliance check; this skill is appropriate because it runs all 9
|
|
12
|
+
categories with pass/fail/warn/skipped statuses and writes structured output.</commentary></example>
|
|
4
13
|
model: inherit
|
|
5
14
|
color: cyan
|
|
6
15
|
---
|
|
@@ -780,11 +780,53 @@ git push origin HEAD
|
|
|
780
780
|
```
|
|
781
781
|
|
|
782
782
|
### 4.4 GitHub Mirror (if configured in Session Config)
|
|
783
|
+
|
|
784
|
+
Three states, three DISTINGUISHABLE outcomes. The predecessor of this block
|
|
785
|
+
(`git remote get-url github 2>/dev/null && git push github HEAD 2>/dev/null || echo "GitHub mirror: not configured"`)
|
|
786
|
+
collapsed a **failed push** into `GitHub mirror: not configured` and exited 0 — git's real
|
|
787
|
+
error went to `/dev/null`, so a broken mirror was indistinguishable from an unconfigured one
|
|
788
|
+
(`.claude/rules/bash-harness-pitfalls.md` — "Silence is not success"). That matters more once
|
|
789
|
+
anything is wired to the mirror (e.g. a Vercel Git deploy): a silently-failing push means the
|
|
790
|
+
downstream artifact never updates and nobody is told.
|
|
791
|
+
|
|
792
|
+
Run it verbatim — `tests/skills/session-end/github-mirror-push.test.mjs` extracts the block
|
|
793
|
+
between the markers and executes it, so no second copy of this command may exist.
|
|
794
|
+
|
|
783
795
|
```bash
|
|
784
|
-
#
|
|
785
|
-
|
|
796
|
+
# --- github-mirror-push:begin ---
|
|
797
|
+
# Only attempt if 'mirror: github' is in Session Config.
|
|
798
|
+
# State 0: not a git repository at all → loud WARN, exit 1. This state was MISSED
|
|
799
|
+
# in the first version and is the reason it is listed first now: outside
|
|
800
|
+
# a repo, `git remote get-url` fails with "fatal: not a git repository",
|
|
801
|
+
# which is indistinguishable from "no such remote" by exit code alone.
|
|
802
|
+
# The block then announced "no 'github' remote configured — skipping
|
|
803
|
+
# (not an error)" and exited 0 — fail-open, in the very fix written to
|
|
804
|
+
# close a fail-open. Found by an adversarial reviewer, not by the author.
|
|
805
|
+
# State 1: no 'github' remote → informational, exit 0 (legitimate for consumer repos)
|
|
806
|
+
# State 2: push succeeded → confirmation WITH the pushed SHA, exit 0
|
|
807
|
+
# State 3: push FAILED → loud WARN on stderr WITH git's real output, exit 1
|
|
808
|
+
if ! git_dir=$(git rev-parse --git-dir 2>&1); then
|
|
809
|
+
echo "WARN GitHub mirror: not a git repository — cannot mirror anything." >&2
|
|
810
|
+
echo " git said: ${git_dir}" >&2
|
|
811
|
+
exit 1
|
|
812
|
+
elif ! mirror_url=$(git remote get-url github 2>&1); then
|
|
813
|
+
echo "GitHub mirror: no 'github' remote configured — skipping (not an error)."
|
|
814
|
+
echo " git said: ${mirror_url}" >&2
|
|
815
|
+
elif push_out=$(git push github HEAD 2>&1); then
|
|
816
|
+
echo "GitHub mirror: pushed $(git rev-parse HEAD) -> ${mirror_url}"
|
|
817
|
+
else
|
|
818
|
+
echo "WARN GitHub mirror PUSH FAILED: $(git rev-parse HEAD) is NOT on ${mirror_url}" >&2
|
|
819
|
+
echo "${push_out}" >&2
|
|
820
|
+
echo "WARN Mirror is stale — anything wired to it (site deploy) will not update." >&2
|
|
821
|
+
exit 1
|
|
822
|
+
fi
|
|
823
|
+
# --- github-mirror-push:end ---
|
|
786
824
|
```
|
|
787
825
|
|
|
826
|
+
State 3 exits non-zero on purpose: it is the only machine-readable signal that the mirror is
|
|
827
|
+
behind. Report it to the operator in the session summary; do not retry silently and do not
|
|
828
|
+
swallow it with `|| true`.
|
|
829
|
+
|
|
788
830
|
## Phase 4a: Auto-Promoted Worktree Cleanup (#575 P3.2)
|
|
789
831
|
|
|
790
832
|
> Skip if `persistence: false` in Session Config. Skip silently if the current worktree is NOT an Auto-promoted sibling (the common case).
|
|
@@ -185,4 +185,4 @@ Finalize session metrics by reading the wave data accumulated during execution:
|
|
|
185
185
|
> - `open_questions_asked` / `open_questions_answered` / `open_questions_deferred` (#773): the three open-question counts from the Phase 1.65 gate's AUQ Call 2 (identical to the `questions_*` payload fields on the `orchestrator.handover.gated` event). Top-level, additive, non-negative integers. Populate ONLY when the gate ran an interactive triage ("Closen + Triage" path). OMIT all three (do NOT write `0`) when the gate was skipped (fail-open / headless / disabled) or took the fast-path — absent = "not measured", `0` = "measured, zero questions". Validator accepts absent/null/non-negative-integer.
|
|
186
186
|
> - `stagnation_events`: populated ONLY when ≥1 stagnation event was logged to `events.jsonl` during this session. When `total == 0`, the field is omitted from the JSONL entry.
|
|
187
187
|
> - `grounding_injections`: populated ONLY when ≥1 `orchestrator.grounding.injected` event was logged to `events.jsonl` during this session. When `count == 0`, the field is omitted from the JSONL entry.
|
|
188
|
-
> - `memory_cleanup_at`:
|
|
188
|
+
> - `memory_cleanup_at`: **derived by the writer, not supplied by the coordinator.** `scripts/emit-session.mjs` sets it to `completed_at` whenever an `orchestrator.memory.cleanup_completed` event for THIS session sits in `events.jsonl` — emitted by every `/memory-cleanup` run in ANY mode (dry-run, apply-pending, OR healthy no-op). **A no-op is still a cleanup; it still emits, so the cadence marker (`readDreamSignals` → `lastCleanupAt`) still advances and `shouldDispatchAutoDream` does not fire a false nudge.** No event → field absent (never `null`). An explicit value already on the record wins and is not overwritten. Do NOT hand-call `stampMemoryCleanup()` here — the coordinator-supplied-boolean form was removed on 2026-08-17 after it silently failed for a real cleanup on 2026-08-14. (#699)
|