@vegastack/skills 0.10.0 → 0.11.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.
Files changed (58) hide show
  1. package/README.md +5 -0
  2. package/package.json +1 -1
  3. package/skill/dev-architect/SKILL.md +7 -4
  4. package/skill/dev-architect/references/conventions.md +93 -0
  5. package/skill/dev-chronicle/SKILL.md +45 -0
  6. package/skill/dev-chronicle/agents/openai.yaml +4 -0
  7. package/skill/dev-chronicle/references/conventions.md +93 -0
  8. package/skill/dev-chronicle/refresh/REFRESH.md +3 -0
  9. package/skill/dev-chronicle/refresh/sources.json +6 -0
  10. package/skill/dev-debug/SKILL.md +43 -0
  11. package/skill/dev-debug/agents/openai.yaml +4 -0
  12. package/skill/dev-debug/references/conventions.md +93 -0
  13. package/skill/dev-debug/references/loop-ladder.md +20 -0
  14. package/skill/dev-debug/refresh/REFRESH.md +3 -0
  15. package/skill/dev-debug/refresh/sources.json +6 -0
  16. package/skill/dev-implement/SKILL.md +41 -36
  17. package/skill/dev-implement/references/conventions.md +93 -0
  18. package/skill/dev-implement/references/ledger-and-resume.md +27 -0
  19. package/skill/dev-implement/scripts/evidence-check.mjs +57 -0
  20. package/skill/dev-implement/scripts/lib/gh.mjs +93 -0
  21. package/skill/dev-implement/scripts/preflight.mjs +101 -0
  22. package/skill/dev-intake/SKILL.md +39 -33
  23. package/skill/dev-intake/references/brief-template.md +27 -12
  24. package/skill/dev-intake/references/conventions.md +93 -0
  25. package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
  26. package/skill/dev-plan/SKILL.md +53 -0
  27. package/skill/dev-plan/agents/openai.yaml +4 -0
  28. package/skill/dev-plan/references/conventions.md +93 -0
  29. package/skill/dev-plan/references/plan-format.md +54 -0
  30. package/skill/dev-plan/refresh/REFRESH.md +3 -0
  31. package/skill/dev-plan/refresh/sources.json +6 -0
  32. package/skill/dev-plan/scripts/plan-lint.mjs +86 -0
  33. package/skill/dev-review/SKILL.md +69 -0
  34. package/skill/dev-review/agents/openai.yaml +4 -0
  35. package/skill/dev-review/assets/review-known-patterns.md.template +30 -0
  36. package/skill/dev-review/references/conventions.md +93 -0
  37. package/skill/dev-review/references/cross-agent.md +39 -0
  38. package/skill/dev-review/references/dispatch-prompts.md +104 -0
  39. package/skill/dev-review/references/security-axis.md +33 -0
  40. package/skill/dev-review/refresh/REFRESH.md +3 -0
  41. package/skill/dev-review/refresh/sources.json +6 -0
  42. package/skill/dev-setup/SKILL.md +7 -5
  43. package/skill/dev-setup/assets/agents-section.md.template +2 -2
  44. package/skill/dev-setup/assets/dev-profile.md.template +4 -3
  45. package/skill/dev-setup/references/conventions.md +93 -0
  46. package/skill/dev-ship/SKILL.md +14 -7
  47. package/skill/dev-ship/references/conventions.md +93 -0
  48. package/skill/dev-ship/references/runbook.md +1 -1
  49. package/skill/dev-ship/scripts/ship-gate.mjs +213 -0
  50. package/skill/dev-status/SKILL.md +45 -0
  51. package/skill/dev-status/agents/openai.yaml +4 -0
  52. package/skill/dev-status/references/conventions.md +93 -0
  53. package/skill/dev-status/refresh/REFRESH.md +3 -0
  54. package/skill/dev-status/refresh/sources.json +6 -0
  55. package/skill/dev-status/scripts/status.mjs +152 -0
  56. package/skill/skillify/SKILL.md +1 -1
  57. package/skill/skillify/references/eval-playbook.md +6 -0
  58. package/skill-integrity.json +78 -14
@@ -0,0 +1,93 @@
1
+ # Workflow conventions
2
+
3
+ The single spec for the artifacts every dev-family skill reads and writes. One home per rule: skills cite this file, never restate it. Everything here is harness-neutral.
4
+
5
+ ## Comment metadata markers
6
+
7
+ Every workflow-generated issue comment opens with an invisible HTML marker followed by a human heading:
8
+
9
+ ```markdown
10
+ <!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
11
+ ## <Human title> (v<n>)
12
+ ```
13
+
14
+ | type | required keys | instances |
15
+ |---|---|---|
16
+ | `approval` | `scope=<brief\|brief+plan\|plan>` | one per approval event |
17
+ | `plan` | `rev` | one, edited in place |
18
+ | `ledger` | `branch` | one, edited in place |
19
+ | `evidence` | `rev branch sha` | one, edited in place |
20
+ | `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
21
+ | `decision` | — | one per decision proposal |
22
+ | `handback` | — | one per stop event |
23
+
24
+ `rev=<n>` and the matching `(v<n>)` heading suffix appear only on revisable artifacts — the brief (issue description), `plan`, and `evidence` — starting at `rev=1`/`(v1)`. Single-event comments (`approval`, `decision`, `handback`) and the `ledger` carry neither. Scripts and agents locate comments strictly by marker, never by heading text. A comment without its marker does not count as the artifact — there is no legacy fallback.
25
+
26
+ ## Operator identity
27
+
28
+ Every human reference in every artifact — approvals, revisions, decisions, changelog attributions, review adjudications — is written `operator (<github-username>)`:
29
+
30
+ - Approval: `Approved by operator (<username>) on DD-MM-YYYY: "<their words>"`
31
+ - Register line: `- DD-MM-YYYY operator (<username>) — <decision>`
32
+
33
+ ## Revision markers
34
+
35
+ Any artifact edited after its first approval: the heading gains `(v2)`, the marker gains `rev=2`, and a `Revisions:` line is appended at the bottom — `v2 — DD-MM-YYYY: <what changed>, per operator (<username>) correction`. Existing revision lines are never rewritten.
36
+
37
+ ## Scope classes
38
+
39
+ Set at intake, applied as a label, announced with its reason (operator can override):
40
+
41
+ - **`research`** — a question to answer; throwaway code allowed, never merged. No branch/PR/changelog; findings + recommendation are the evidence comment.
42
+ - **`quick-build`** — small change and the flow being changed already exists in the repo to read. Brief (description) + plan (comment) are drafted in the same conversation; **one approval covers both**; then straight to `ready`.
43
+ - **`full-plan`** — big or new ground. Brief approval → `needs-plan` → a separate, fresh-grounded planning session posts the plan → `needs-operator` → "plan approved" → `ready`. Multi-deliverable work becomes an epic; each sub-issue is classified independently.
44
+
45
+ Scope calls are revisited through the one-way ratchet, whose rules and mechanics live in the `dev-plan` skill — the one home for upgrade/downgrade behavior.
46
+
47
+ ## Labels
48
+
49
+ State — exactly one per issue (creation colors live in dev-setup's labels row, their one home):
50
+
51
+ | label | meaning |
52
+ |---|---|
53
+ | `needs-operator` | waiting on the operator: a question, a brief or plan to approve, a proposal |
54
+ | `needs-plan` | brief approved; waiting for the planning stage (full-plan only) |
55
+ | `ready` | fully approved — an agent may start |
56
+ | `working` | claimed, in progress; the ledger comment shows live progress |
57
+ | `for-operator` | done — evidence posted, awaiting operator review |
58
+
59
+ Modifiers (may coexist with the state label): `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents, only where the org has no native Epic issue type).
60
+
61
+ ## Titles, types, hierarchy
62
+
63
+ - **Title prefixes** on issues, branches, and PRs identically: dev.md's `branch:` knob type list (that knob stays the list's one home) plus `research:` for research issues. PR title = issue title.
64
+ - **Native issue types** where the org defines them: Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (label fallback otherwise).
65
+ - **Hierarchy:** epic parent = map only (Destination · Decisions so far as one-line gists · Not clear yet · Out of scope), children attached as native sub-issues; issues = the unit of work (brief in description, own approvals/branch/PR/evidence); tasks = checkboxes **in the plan comment only**. Blockers use native issue dependencies; phases use milestones. Only issues — never epics — get `ready`. GitHub caps issue bodies and comments at ~65,536 characters; what a plan nearing that cap means is the `dev-plan` ratchet's call.
66
+
67
+ ## The ledger
68
+
69
+ Maintained by the implement session as one comment, edited in place:
70
+
71
+ ```markdown
72
+ <!-- vsk:v1 type=ledger branch=<branch> -->
73
+ ## Ledger — <branch>
74
+ - Task <N>: complete (commits <base7>..<head7>[, review clean | K parked])
75
+ - Task <N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
76
+ - Ruling: <what> — <why> — cost if wrong: <cost>
77
+ - Task <N>: parked — <finding> — Ruling: <why the code stands>
78
+ - Deferred minor: <one-liner>
79
+ ```
80
+
81
+ **Resume protocol:** a fresh, compacted, or (operator-handed) takeover session reads, in order: the brief → the plan comment → the ledger → `git log` on the branch — **nothing else**. Tasks with a `complete` line are DONE, never re-executed; a task whose last line is a fix round resumes at the next round. After compaction, trust the ledger and `git log` over recollection. Every `Ruling:` line surfaces in the evidence comment — a ruling that dies with the session was a decision made in secret.
82
+
83
+ ## `.vegastack/.tmp/` workspace
84
+
85
+ All transitory artifacts — subagent reports, review packages, plan drafts, extracted diffs — live at `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue intake drafts, which have no number yet: `.vegastack/.tmp/intake-<slug>/`), kept out of git by a self-ignoring `.gitignore` (`printf '*\n' > .vegastack/.tmp/.gitignore`, created on first use). Subagents write full reports to files there and return only short status — a dead subagent's findings survive on disk, and the primary session never holds full reports in context. The workspace lives in the working tree (never under `.git/`, which harnesses protect from writes).
86
+
87
+ ## Verification gate
88
+
89
+ Before claiming any status: **IDENTIFY** the command that proves the claim → **RUN** it fresh and complete → **READ** the full output and exit code → only then claim, with the evidence. "Should pass", a previous run, or a subagent's say-so are never evidence. Guard scripts follow the same doctrine: machine-verifiable facts **block** (exit 2 with the reason); regex or judgment heuristics only **warn** — no AI inference inside guards, and an unverifiable state fails closed.
90
+
91
+ ## Plain-language collaboration
92
+
93
+ Every skill run ends with a simple-language summary: what happened, which paths were taken — cross-agent invocations announced at trigger time AND summarized at the end — and what is worth the operator double-checking. Use mermaid or ASCII diagrams in issues wherever a picture beats prose. A vague or self-contradicting operator answer gets pushback with concrete options, never silent absorption.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: dev-ship
3
- description: Create the pull request and merge for a finished issue, each only on the user's explicit word, then run the project's Ship runbook — releases, guards, deploys. Use when the user says "make the PR", "open a pull request" for an issue, "ship it", "merge it", "merge issue 12", "release", "release everything since the last tag", or asks to close out a reviewed issue, merge a bot PR, or roll back a bad release (roll-forward). Verifies the issue is at for-operator with evidence and its changelog entry, links the PR to the issue, merges on the separate merge instruction, and records approved decisions. Not for implementing issues (dev-implement) or writing and approving them (dev-intake).
3
+ description: Land finished work, each step only on the operator's explicit word. Use when the user says "make the PR", "open a pull request" for an issue, "ship it", "merge it", "merge issue 12", "release", "release everything since the last tag", or asks to close out a reviewed for-operator issue, merge a bot PR (Renovate, Dependabot), or roll back a bad release. Not for implementing issues (dev-implement), reviewing them (dev-review), or writing and approving them (dev-intake).
4
4
  ---
5
5
 
6
6
  # dev-ship
@@ -13,23 +13,28 @@ Nearest neighbor: `dev-implement` produces the `for-operator` issue with its evi
13
13
 
14
14
  On the user's PR instruction:
15
15
 
16
- - Verify the issue is at `for-operator` with the evidence comment present, and the branch is pushed. Not there yet → say what's missing instead of creating a premature PR.
16
+ - Run the deterministic guard first: `node <path-to-this-skill>/scripts/ship-gate.mjs --issue <n> --branch <name> --json` (add `--repo <o/r> --dev-md <path>` outside the project root) — it re-runs the project check command fresh from the branch's own checkout, requires the evidence sha to equal the branch head (the corrections loop is the only reconciliation path), the changelog entry, the chronicle entry where the knob says `on`, a clean-or-adjudicated review verdict, and greps added lines for leftover `[DEBUG-` tags; exit 2 stops you with its reasons, warnings are read-twice signals.
17
+ - Verify the issue is at `for-operator` with the evidence comment present — including its `**Docs:**` line (brief/plan revisions in sync) — and the branch is pushed. Not there yet → say what's missing instead of creating a premature PR. Docs out of sync is corrections work: never patch a brief or plan from inside dev-ship.
17
18
  - Verify the changelog state matches the evidence comment's `**Changelog:**` line: a behavior-changing branch carries its entry per dev.md's `changelog:` knob (changesets: a `.changeset/*.md` in the diff; keep-a-changelog: the diff adds lines to CHANGELOG.md), while `none` with a reason that holds up (docs-only, test-only) is fine. An unexplained miss → corrections loop, not a PR.
18
19
  - `gh pr create` from the task branch: title from the issue, body is `Closes #<n>` plus a link to the evidence comment — the issue holds the report; the PR links it rather than duplicating it.
19
20
  - No draft PRs unless the user asks for one.
20
- - If required checks fail on the PR, that's implement work: hand the failures to the corrections loop, update the evidence comment, and tell the user. Under `gates: 2` the standing ship word holds once checks are green again — unless the fix changed behavior, which goes back to the user (same rule as a merge conflict).
21
+ - If required checks fail on the PR, that's implement work: hand the failures to the corrections loop, update the evidence comment, and tell the user. Under `gates: 2` the standing ship word holds once checks are green again — subject to Gate 2's staleness bound (behavior change or >7 days → one-sentence re-confirm).
21
22
  - A direct chat change (dev-implement's no-issue path) ships on the same words: the chat request stands in for the recorded approval, the PR body carries the evidence instead of linking an issue comment, and the changelog rule applies unchanged.
22
23
  - User corrections left on the PR itself flow through the same corrections loop on the same branch — the PR updates with the push; nothing gets recreated.
23
24
 
24
25
  With `gates: 1` there is no PR: the same verifications run, then the ship word triggers the merge below directly ([runbook](references/runbook.md) has the mechanics).
25
26
 
27
+ | Excuse (observed) | Reality |
28
+ |---|---|
29
+ | "Opening a PR is preparation, not shipping — it pushes nothing… exactly the state the workflow wants finished work parked in." | Under `gates: 3` the PR is a gate spent only by the operator's word. Finished work parks on the pushed branch; a draft PR is still a PR nobody asked for. |
30
+
26
31
  ## Gate 2 — the merge
27
32
 
28
33
  On the user's merge instruction:
29
34
 
30
35
  - Re-check that the PR head is still the revision the evidence comment names and checks are green — a branch that moved since review gets re-verified before it lands.
31
- - Pending `Decision:` lines exist (issue comments, or the evidence comment's `**Decision:**` line) → name them in the merge confirmation — "merging will record: …" — so the operator's word demonstrably covers them; never append on inferred consent. On the word, append each to the register dev.md names (`decisions:` knob) in its `- DD-MM-YYYY (github-username) — …` format; the register is append-only and this is its moment.
32
- - A merge conflict with the default branch is corrections work: update the branch, re-verify what the update touched, and the standing merge instruction holds once checks are green again — unless the update changed behavior, which goes back to the user.
36
+ - Pending `Decision:` lines exist (issue comments, or the evidence comment's `**Decision:**` line) → name them in the merge confirmation — "merging will record: …" — so the operator's word demonstrably covers them; never append on inferred consent. On the word, append each to the register dev.md names (`decisions:` knob) in its `- DD-MM-YYYY operator (github-username) — …` format; the register is append-only and this is its moment.
37
+ - A merge conflict with the default branch is corrections work: update the branch, re-verify what the update touched, and the standing merge instruction holds once checks are green again — unless the update changed behavior, or more than 7 days have passed since the word; either way, re-confirm with one sentence rather than acting on a stale instruction.
33
38
  - Merge per the dev.md `merge` knob (default `gh pr merge --squash`; `gates: 1` merges locally per the same knob and pushes). `Closes #<n>` closes the issue; confirm both happened.
34
39
  - A bot PR (Renovate, Dependabot) has no issue or evidence comment and merging it is still shipping: green checks qualify it, only the operator's explicit word — per PR or per named batch — merges it; majors and security advisories get named before their word is acted on.
35
40
 
@@ -37,8 +42,10 @@ On the user's merge instruction:
37
42
 
38
43
  Merge is not the end when dev.md has a `## Ship` section: follow its steps in order — `auto:` lines you just do, `ask:` lines wait for the operator's word, `guard:` lines are deterministic checks you run locally at their position (their CI copies are the backstop). With `release: per-merge`, the runbook is part of shipping the issue; with `release: on-request`, it runs only when the operator says "release" (covering everything merged since the last one). Report each step's outcome; a failing step — guard included — stops the sequence and goes to the operator, never skipped past. Execution detail, release batching, direct-to-main, bot PRs, and rollback: [runbook](references/runbook.md).
39
44
 
40
- Rollback is never a force-push: follow the Ship section's rollback line — roll forward through the normal flow. A gotcha here (a step that surprised you, an instruction the operator had to repeat) is one proposed line folded into the runbook; a directional gotcha that passes dev.md's Decisions test is a register proposal instead, on the user's yes.
45
+ Rollback is never a force-push: follow the Ship section's rollback line — roll forward through the normal flow. Gotchas surfaced here feed the Report's closing retro below.
41
46
 
42
47
  ## Report
43
48
 
44
- One short confirmation each gate: what was created or merged, the link, decisions recorded, and anything that still needs the user (failing check, failing guard, moved head, missing evidence or changelog entry). When a gate's condition isn't met, the answer is what's missing — the gate itself never gets skipped to be helpful.
49
+ One short confirmation each gate, in plain language: what was created or merged, the link, decisions recorded, and anything that still needs the operator (failing check, failing guard, moved head, missing evidence or changelog entry). When a gate's condition isn't met, the answer is what's missing — the gate itself never gets skipped to be helpful.
50
+
51
+ Close every ship with the retro: any bounce, gotcha, or instruction the operator had to repeat during this issue? Propose the ONE dev.md (or runbook) line that would have prevented it — fold into an existing line, never append a log; a directional gotcha becomes a register proposal instead. Each lands only on the operator's yes.
@@ -0,0 +1,93 @@
1
+ # Workflow conventions
2
+
3
+ The single spec for the artifacts every dev-family skill reads and writes. One home per rule: skills cite this file, never restate it. Everything here is harness-neutral.
4
+
5
+ ## Comment metadata markers
6
+
7
+ Every workflow-generated issue comment opens with an invisible HTML marker followed by a human heading:
8
+
9
+ ```markdown
10
+ <!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
11
+ ## <Human title> (v<n>)
12
+ ```
13
+
14
+ | type | required keys | instances |
15
+ |---|---|---|
16
+ | `approval` | `scope=<brief\|brief+plan\|plan>` | one per approval event |
17
+ | `plan` | `rev` | one, edited in place |
18
+ | `ledger` | `branch` | one, edited in place |
19
+ | `evidence` | `rev branch sha` | one, edited in place |
20
+ | `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
21
+ | `decision` | — | one per decision proposal |
22
+ | `handback` | — | one per stop event |
23
+
24
+ `rev=<n>` and the matching `(v<n>)` heading suffix appear only on revisable artifacts — the brief (issue description), `plan`, and `evidence` — starting at `rev=1`/`(v1)`. Single-event comments (`approval`, `decision`, `handback`) and the `ledger` carry neither. Scripts and agents locate comments strictly by marker, never by heading text. A comment without its marker does not count as the artifact — there is no legacy fallback.
25
+
26
+ ## Operator identity
27
+
28
+ Every human reference in every artifact — approvals, revisions, decisions, changelog attributions, review adjudications — is written `operator (<github-username>)`:
29
+
30
+ - Approval: `Approved by operator (<username>) on DD-MM-YYYY: "<their words>"`
31
+ - Register line: `- DD-MM-YYYY operator (<username>) — <decision>`
32
+
33
+ ## Revision markers
34
+
35
+ Any artifact edited after its first approval: the heading gains `(v2)`, the marker gains `rev=2`, and a `Revisions:` line is appended at the bottom — `v2 — DD-MM-YYYY: <what changed>, per operator (<username>) correction`. Existing revision lines are never rewritten.
36
+
37
+ ## Scope classes
38
+
39
+ Set at intake, applied as a label, announced with its reason (operator can override):
40
+
41
+ - **`research`** — a question to answer; throwaway code allowed, never merged. No branch/PR/changelog; findings + recommendation are the evidence comment.
42
+ - **`quick-build`** — small change and the flow being changed already exists in the repo to read. Brief (description) + plan (comment) are drafted in the same conversation; **one approval covers both**; then straight to `ready`.
43
+ - **`full-plan`** — big or new ground. Brief approval → `needs-plan` → a separate, fresh-grounded planning session posts the plan → `needs-operator` → "plan approved" → `ready`. Multi-deliverable work becomes an epic; each sub-issue is classified independently.
44
+
45
+ Scope calls are revisited through the one-way ratchet, whose rules and mechanics live in the `dev-plan` skill — the one home for upgrade/downgrade behavior.
46
+
47
+ ## Labels
48
+
49
+ State — exactly one per issue (creation colors live in dev-setup's labels row, their one home):
50
+
51
+ | label | meaning |
52
+ |---|---|
53
+ | `needs-operator` | waiting on the operator: a question, a brief or plan to approve, a proposal |
54
+ | `needs-plan` | brief approved; waiting for the planning stage (full-plan only) |
55
+ | `ready` | fully approved — an agent may start |
56
+ | `working` | claimed, in progress; the ledger comment shows live progress |
57
+ | `for-operator` | done — evidence posted, awaiting operator review |
58
+
59
+ Modifiers (may coexist with the state label): `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents, only where the org has no native Epic issue type).
60
+
61
+ ## Titles, types, hierarchy
62
+
63
+ - **Title prefixes** on issues, branches, and PRs identically: dev.md's `branch:` knob type list (that knob stays the list's one home) plus `research:` for research issues. PR title = issue title.
64
+ - **Native issue types** where the org defines them: Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (label fallback otherwise).
65
+ - **Hierarchy:** epic parent = map only (Destination · Decisions so far as one-line gists · Not clear yet · Out of scope), children attached as native sub-issues; issues = the unit of work (brief in description, own approvals/branch/PR/evidence); tasks = checkboxes **in the plan comment only**. Blockers use native issue dependencies; phases use milestones. Only issues — never epics — get `ready`. GitHub caps issue bodies and comments at ~65,536 characters; what a plan nearing that cap means is the `dev-plan` ratchet's call.
66
+
67
+ ## The ledger
68
+
69
+ Maintained by the implement session as one comment, edited in place:
70
+
71
+ ```markdown
72
+ <!-- vsk:v1 type=ledger branch=<branch> -->
73
+ ## Ledger — <branch>
74
+ - Task <N>: complete (commits <base7>..<head7>[, review clean | K parked])
75
+ - Task <N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
76
+ - Ruling: <what> — <why> — cost if wrong: <cost>
77
+ - Task <N>: parked — <finding> — Ruling: <why the code stands>
78
+ - Deferred minor: <one-liner>
79
+ ```
80
+
81
+ **Resume protocol:** a fresh, compacted, or (operator-handed) takeover session reads, in order: the brief → the plan comment → the ledger → `git log` on the branch — **nothing else**. Tasks with a `complete` line are DONE, never re-executed; a task whose last line is a fix round resumes at the next round. After compaction, trust the ledger and `git log` over recollection. Every `Ruling:` line surfaces in the evidence comment — a ruling that dies with the session was a decision made in secret.
82
+
83
+ ## `.vegastack/.tmp/` workspace
84
+
85
+ All transitory artifacts — subagent reports, review packages, plan drafts, extracted diffs — live at `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue intake drafts, which have no number yet: `.vegastack/.tmp/intake-<slug>/`), kept out of git by a self-ignoring `.gitignore` (`printf '*\n' > .vegastack/.tmp/.gitignore`, created on first use). Subagents write full reports to files there and return only short status — a dead subagent's findings survive on disk, and the primary session never holds full reports in context. The workspace lives in the working tree (never under `.git/`, which harnesses protect from writes).
86
+
87
+ ## Verification gate
88
+
89
+ Before claiming any status: **IDENTIFY** the command that proves the claim → **RUN** it fresh and complete → **READ** the full output and exit code → only then claim, with the evidence. "Should pass", a previous run, or a subagent's say-so are never evidence. Guard scripts follow the same doctrine: machine-verifiable facts **block** (exit 2 with the reason); regex or judgment heuristics only **warn** — no AI inference inside guards, and an unverifiable state fails closed.
90
+
91
+ ## Plain-language collaboration
92
+
93
+ Every skill run ends with a simple-language summary: what happened, which paths were taken — cross-agent invocations announced at trigger time AND summarized at the end — and what is worth the operator double-checking. Use mermaid or ASCII diagrams in issues wherever a picture beats prose. A vague or self-contradicting operator answer gets pushback with concrete options, never silent absorption.
@@ -33,4 +33,4 @@ A bot PR has no issue, no brief, no evidence comment — and merging it is still
33
33
 
34
34
  ## Guard failure at ship time
35
35
 
36
- A local `guard:` failure (missing changelog entry, tag/version mismatch) means the branch or release prep is incomplete: route it to dev-implement's corrections loop, get the evidence comment updated, then resume at the failed step. Never edit release artifacts inline just to get past a guard.
36
+ A local `guard:` failure (missing changelog entry, tag/version mismatch) means the branch or release prep is incomplete: route it to dev-implement's corrections loop, get the evidence comment updated, then resume at the failed step. Never edit release artifacts inline just to get past a guard. `ship-gate.mjs` speaks the same language: exit 0 pass · 1 pass-with-warnings (read them twice, they never block) · 2 blocked with its reasons printed — a 2 routes to corrections exactly like a failing `guard:` line.
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env node
2
+ // dev-ship guard, run at Gate 1 before a PR (and re-run before merge): the
3
+ // deterministic facts that make a hand-back shippable. Facts block; the
4
+ // rationalization scan over the evidence text only warns — regex heuristics
5
+ // never block. Self-contained (ships with dev-ship; no cross-skill imports).
6
+ //
7
+ // Exit codes: 0 pass · 1 pass-with-warnings · 2 blocked (reasons printed).
8
+ // Usage: node ship-gate.mjs --issue <n> --branch <name> [--repo o/r] [--dev-md <path>]
9
+ // [--base main] [--allow-no-changelog "<reason>"] --json
10
+ import { execFileSync } from 'node:child_process';
11
+ import { readFileSync } from 'node:fs';
12
+ import { resolve } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+
15
+ const RATIONALIZATIONS = [
16
+ /skip(ping)? tests? for now/i,
17
+ /pre-existing (issue|bug)/i,
18
+ /fix (this|it) later/i,
19
+ /(tests?|coverage) (is|are) (failing|broken) but/i,
20
+ ];
21
+
22
+ function sh(cmd, args) {
23
+ // VSK_GH is a TEST SEAM (stubs gh in unit tests); git always runs real.
24
+ const bin = cmd === 'gh' ? (process.env.VSK_GH || 'gh') : cmd;
25
+ return execFileSync(bin, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env } }).trim();
26
+ }
27
+
28
+ // Adjudication means OPEN FINDINGS were ruled on at the loop cap. Routine
29
+ // ledger vocabulary ("Ruling:", a mid-build "parked", "nothing parked") must
30
+ // not lift a needs-fixes block — only "adjudicat*" or a finding-tied park
31
+ // ("Finding [N] ... parked") counts.
32
+ export function reviewAdjudicated(evidenceBody) {
33
+ const section = /\*\*Review:\*\*[\s\S]*?(?=\n\*\*[A-Z]|\nBranch:|$)/.exec(evidenceBody ?? '')?.[0] ?? '';
34
+ return /adjudicat/i.test(section) || /finding \[\d+\][^\n]*parked/i.test(section);
35
+ }
36
+
37
+ export function parseMarker(body) {
38
+ const match = /<!--\s*vsk:v1\s+([^>]*?)\s*-->/.exec(body ?? '');
39
+ if (!match) return null;
40
+ const keys = {};
41
+ for (const pair of match[1].split(/\s+/)) {
42
+ const eq = pair.indexOf('=');
43
+ if (eq > 0) keys[pair.slice(0, eq)] = pair.slice(eq + 1);
44
+ }
45
+ return { keys };
46
+ }
47
+
48
+ // An entry means an ADDED "## " heading in the file-scoped diff — a deleted
49
+ // file or a typo edit to an old entry is not a new entry.
50
+ export function chronicleEntryAdded(fileDiff) {
51
+ return /^\+## /m.test(fileDiff ?? '');
52
+ }
53
+
54
+ // Pure evaluation over gathered facts — unit tests drive this directly.
55
+ export function evaluateShipGate(facts) {
56
+ const blocks = [];
57
+ const warns = [];
58
+ const {
59
+ evidence, // { body } | null
60
+ reviewVerdict, // 'clean' | 'needs-fixes' | null
61
+ adjudicated, // boolean: evidence Review section carries adjudication rulings
62
+ headSha, // short sha of the branch head
63
+ diffText, // full diff vs base
64
+ changelogTouched, // boolean: diff adds a changelog/changeset entry
65
+ // chronicleOn/chronicleTouched (via facts.*): dev.md chronicle knob and
66
+ // whether the diff adds a "## " chronicle entry heading
67
+ allowNoChangelog, // reason string | undefined
68
+ checkExit, // number | null (null = no check command configured)
69
+ } = facts;
70
+
71
+ if (!evidence) {
72
+ blocks.push('no evidence comment (marker type=evidence) on the issue');
73
+ return { blocks, warns };
74
+ }
75
+ const marker = parseMarker(evidence.body);
76
+ const evidenceSha = marker?.keys?.sha ?? '';
77
+
78
+ if (!/^[0-9a-f]{7,40}$/.test(evidenceSha)) {
79
+ blocks.push(`evidence marker carries no valid sha= (found "${evidenceSha || 'nothing'}") — the shipped revision must be named`);
80
+ } else if (!headSha.startsWith(evidenceSha) && !evidenceSha.startsWith(headSha)) {
81
+ // Strict equality, no reconciliation window: the corrections loop updates
82
+ // the evidence comment (Docs line AND sha) after every change, so a
83
+ // mismatched sha means unrecorded work. An "edited since the commit"
84
+ // window was spoofable by any comment edit and was removed.
85
+ blocks.push(`branch head ${headSha} moved past evidence sha ${evidenceSha} — the corrections loop must re-verify and update the evidence comment (Docs line + new sha) before shipping`);
86
+ }
87
+
88
+ if (!changelogTouched && !allowNoChangelog) {
89
+ blocks.push('no changelog/changeset entry in the diff and no --allow-no-changelog reason given');
90
+ }
91
+
92
+ if (facts.chronicleOn && !facts.chronicleTouched && !allowNoChangelog) {
93
+ blocks.push('dev.md says chronicle: on but the diff adds no .vegastack/chronicle.md entry (the same --allow-no-changelog reason covers docs/test-only branches)');
94
+ }
95
+ if (allowNoChangelog && (!changelogTouched || (facts.chronicleOn && !facts.chronicleTouched))) {
96
+ warns.push(`--allow-no-changelog exercised ("${allowNoChangelog}") — it excused: ${[!changelogTouched ? 'changelog' : null, facts.chronicleOn && !facts.chronicleTouched ? 'chronicle' : null].filter(Boolean).join(' + ')}`);
97
+ }
98
+
99
+ if (reviewVerdict !== 'clean' && !adjudicated) {
100
+ blocks.push(`latest review verdict is ${reviewVerdict ?? 'absent'} and the evidence Review section carries no adjudication`);
101
+ }
102
+
103
+ if (facts.checkoutMismatch) {
104
+ blocks.push(facts.checkoutMismatch);
105
+ }
106
+ if (facts.checkMissing) {
107
+ warns.push('dev.md has no check command on its commands: line — the fresh-run gate could not run; verify by hand');
108
+ }
109
+ if (checkExit !== null && checkExit !== 0) {
110
+ blocks.push(`the project check command exited ${checkExit} on a fresh run — a claim is never trusted, always re-proven`);
111
+ }
112
+
113
+ // Added lines only, and only the REAL tag shape ([DEBUG- + hex): docs that
114
+ // document the tag write placeholders like [DEBUG-<4hex>] and must not block.
115
+ if (/^\+(?!\+\+).*\[DEBUG-[0-9a-f]{4}\]/m.test(diffText)) {
116
+ blocks.push('the diff adds [DEBUG- tagged instrumentation — dev-debug cleanup was skipped');
117
+ }
118
+
119
+ for (const pattern of RATIONALIZATIONS) {
120
+ const hit = pattern.exec(evidence.body);
121
+ if (hit) warns.push(`rationalization wording in evidence: "${hit[0]}" — heuristics never block, but read it twice`);
122
+ }
123
+
124
+ return { blocks, warns };
125
+ }
126
+
127
+ export function gatherFacts(flags) {
128
+ const repo = flags.repo || sh('gh', ['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner']);
129
+ const base = flags.base || 'main';
130
+ const branch = flags.branch;
131
+ const comments = JSON.parse(sh('gh', ['api', `repos/${repo}/issues/${flags.issue}/comments`, '--paginate']));
132
+
133
+ let evidence = null;
134
+ let reviewVerdict = null;
135
+ for (const comment of comments) {
136
+ const marker = parseMarker(comment.body);
137
+ if (marker?.keys?.type === 'evidence') evidence = { body: comment.body, updatedAt: comment.updated_at };
138
+ if (marker?.keys?.type === 'review') reviewVerdict = marker.keys.verdict ?? null;
139
+ }
140
+ const adjudicated = reviewAdjudicated(evidence?.body);
141
+
142
+ const headSha = sh('git', ['rev-parse', '--short=7', branch]);
143
+ const diffText = sh('git', ['diff', `${base}...${branch}`]);
144
+ // The fresh check run and dev.md read use the WORKING TREE — they prove
145
+ // nothing unless the checkout is the branch under review.
146
+ const checkoutSha = sh('git', ['rev-parse', 'HEAD']);
147
+ const branchSha = sh('git', ['rev-parse', branch]);
148
+ const checkoutMismatch = checkoutSha === branchSha
149
+ ? null
150
+ : `the current checkout (${checkoutSha.slice(0, 7)}) is not the branch under review (${branch} @ ${branchSha.slice(0, 7)}) — run ship-gate from that branch so the fresh check proves the right code`;
151
+
152
+ const devMd = readFileSync(flags['dev-md'] || '.vegastack/dev.md', 'utf8');
153
+ const changelogKnob = (/^changelog:\s*(\S+)/m.exec(devMd) || [])[1] ?? 'none';
154
+ // Added files/lines only — a deleted changeset or the +++ diff header must
155
+ // not count as an entry.
156
+ const changelogTouched = changelogKnob === 'none'
157
+ ? true
158
+ : changelogKnob === 'changesets'
159
+ ? /^\+\+\+ b\/\.changeset\/(?!config)/m.test(diffText)
160
+ : /^\+(?!\+\+)[^\n]*\S/m.test(sh('git', ['diff', `${base}...${branch}`, '--', 'CHANGELOG.md']) || '');
161
+
162
+ const chronicleOn = /^chronicle:\s*on\s*(#|$)/m.test(devMd);
163
+ const chronicleTouched = chronicleEntryAdded(sh('git', ['diff', `${base}...${branch}`, '--', '.vegastack/chronicle.md']) || '');
164
+
165
+ let checkExit = null;
166
+ const checkCmd = (/^commands:.*?check\s+`([^`]+)`/m.exec(devMd) || [])[1];
167
+ const checkMissing = !checkCmd;
168
+ if (checkCmd) {
169
+ try {
170
+ execFileSync('sh', ['-c', checkCmd], { stdio: ['ignore', 'pipe', 'pipe'] });
171
+ checkExit = 0;
172
+ } catch (error) {
173
+ checkExit = error.status ?? 1;
174
+ }
175
+ }
176
+
177
+ return {
178
+ evidence, reviewVerdict, adjudicated, headSha, diffText,
179
+ changelogTouched, chronicleOn, chronicleTouched,
180
+ allowNoChangelog: flags['allow-no-changelog'], checkExit, checkMissing, checkoutMismatch,
181
+ };
182
+ }
183
+
184
+ const invokedDirectly = process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
185
+ if (invokedDirectly) {
186
+ const argv = process.argv.slice(2);
187
+ const json = argv.includes('--json');
188
+ const get = (flag) => { const i = argv.indexOf(flag); return i === -1 ? undefined : argv[i + 1]; };
189
+ const flags = {
190
+ issue: get('--issue'), branch: get('--branch'), repo: get('--repo'), base: get('--base'),
191
+ 'dev-md': get('--dev-md'), 'allow-no-changelog': get('--allow-no-changelog'), json,
192
+ };
193
+ let outcome;
194
+ if (!flags.issue || !flags.branch) {
195
+ outcome = { blocks: ['usage: ship-gate.mjs --issue <n> --branch <name> [--json]'], warns: [] };
196
+ } else {
197
+ try {
198
+ outcome = evaluateShipGate(gatherFacts(flags));
199
+ } catch (error) {
200
+ outcome = { blocks: [`cannot verify: ${error.message}`], warns: [] };
201
+ }
202
+ }
203
+ const ok = outcome.blocks.length === 0;
204
+ const exitCode = ok ? (outcome.warns.length ? 1 : 0) : 2;
205
+ if (json) {
206
+ console.log(JSON.stringify({ guard: 'ship-gate', ok, ...outcome }, null, 2));
207
+ } else {
208
+ console.log(`ship-gate: ${ok ? (outcome.warns.length ? 'pass with warnings' : 'pass') : 'BLOCKED'}`);
209
+ for (const b of outcome.blocks) console.log(` block: ${b}`);
210
+ for (const w of outcome.warns) console.log(` warn: ${w}`);
211
+ }
212
+ process.exit(exitCode);
213
+ }
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: dev-status
3
+ description: The operator's board — whose move is it, across every issue in the dev workflow. Use when asked "status", "what needs me", "where are we", "what's in flight", "anything stale?", "what should I look at next", or for a board overview of needs-operator / needs-plan / ready / working / for-operator issues. Not for the project's history ("catch me up" is dev-chronicle), implementing or reviewing anything, or repo bootstrap (dev-setup).
4
+ ---
5
+
6
+ # dev-status
7
+
8
+ One question, answered from deterministic data: **whose move is it?** The bundled script gathers; this skill orders and narrates — it never invents state, and an unverifiable board is reported as exactly that.
9
+
10
+ Nearest neighbors: `dev-chronicle` answers "how did we get here"; this skill answers "what needs whom right now". Formats read via the `dev-setup` skill's `references/conventions.md` markers.
11
+
12
+ ## Gather
13
+
14
+ ```
15
+ node <path-to-this-skill>/scripts/status.mjs --stale-days 3 --json
16
+ ```
17
+
18
+ Read-only; it returns the board (open issues per state label with age, scope, risky), task progress `x/y` from plan-comment checkboxes, ledger movement for `working` issues (stale = no ledger edit within `--stale-days`, default 3), open PRs with check state, pending unrecorded `Decision:` proposals, and the last chronicle entry. Exit 2 = cannot verify (offline, unauthenticated) — report the gap plainly and stop; never render a guessed board.
19
+
20
+ ## Render — names, never bare numbers
21
+
22
+ ```markdown
23
+ ## Status — <repo> · DD-MM
24
+
25
+ Needs you (N):
26
+ - <linked title> — <state> <age>d: <one line: what it waits for and the word needed>
27
+ Waiting on plan (N): - <linked title> — needs-plan <age>d
28
+ Ready to build (N): - <linked title> — <scope>
29
+ In flight (N): - <linked title> — working, task <x>/<y>, ledger moved <n>d ago
30
+ Stale (N): - <linked title> — working <age>d, ledger silent <n>d → check or reclaim
31
+ Open PRs (N): - <linked title> — checks <green|pending-or-red|no-checks>
32
+ Pending decisions (N): "<gist>" (<linked issue>) — records at that issue's merge
33
+ Last chronicle chapter: <date> — <title>
34
+ Next: <the single most valuable operator action, and why>
35
+ ```
36
+
37
+ - **Needs you** first (for-operator + needs-operator merged, oldest first) — it's the operator's queue; everything else is context.
38
+ - Sections with zero entries are omitted, not rendered empty. A completely quiet board is one line: "Nothing needs you — <n> issues ready for agents, nothing in flight."
39
+ - `risky` issues get their flag shown inline wherever they appear.
40
+ - **Next** is one line, chosen not computed-looking: the action that unblocks the most (a plan approval blocking several ready issues beats a lone review).
41
+ - <linked title> means a markdown link wrapping the issue/PR title around its URL; numbers ride inside the link, never stand alone.
42
+
43
+ ## Honesty rules
44
+
45
+ Data comes only from the script; ordering, the wait-reason one-liners, and Next are the skill's judgment — clearly judgment, never dressed as data. A stale `working` issue is a fact to surface, not an accusation: "check or reclaim" is the operator's call (a takeover still needs their explicit handover, per dev-implement). Close with the plain-language summary only when invoked as part of a larger run; standalone, the report IS the summary.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "dev-status"
3
+ short_description: "The operator's board — whose move is it"
4
+ default_prompt: "Use $dev-status to show what needs me."
@@ -0,0 +1,93 @@
1
+ # Workflow conventions
2
+
3
+ The single spec for the artifacts every dev-family skill reads and writes. One home per rule: skills cite this file, never restate it. Everything here is harness-neutral.
4
+
5
+ ## Comment metadata markers
6
+
7
+ Every workflow-generated issue comment opens with an invisible HTML marker followed by a human heading:
8
+
9
+ ```markdown
10
+ <!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
11
+ ## <Human title> (v<n>)
12
+ ```
13
+
14
+ | type | required keys | instances |
15
+ |---|---|---|
16
+ | `approval` | `scope=<brief\|brief+plan\|plan>` | one per approval event |
17
+ | `plan` | `rev` | one, edited in place |
18
+ | `ledger` | `branch` | one, edited in place |
19
+ | `evidence` | `rev branch sha` | one, edited in place |
20
+ | `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
21
+ | `decision` | — | one per decision proposal |
22
+ | `handback` | — | one per stop event |
23
+
24
+ `rev=<n>` and the matching `(v<n>)` heading suffix appear only on revisable artifacts — the brief (issue description), `plan`, and `evidence` — starting at `rev=1`/`(v1)`. Single-event comments (`approval`, `decision`, `handback`) and the `ledger` carry neither. Scripts and agents locate comments strictly by marker, never by heading text. A comment without its marker does not count as the artifact — there is no legacy fallback.
25
+
26
+ ## Operator identity
27
+
28
+ Every human reference in every artifact — approvals, revisions, decisions, changelog attributions, review adjudications — is written `operator (<github-username>)`:
29
+
30
+ - Approval: `Approved by operator (<username>) on DD-MM-YYYY: "<their words>"`
31
+ - Register line: `- DD-MM-YYYY operator (<username>) — <decision>`
32
+
33
+ ## Revision markers
34
+
35
+ Any artifact edited after its first approval: the heading gains `(v2)`, the marker gains `rev=2`, and a `Revisions:` line is appended at the bottom — `v2 — DD-MM-YYYY: <what changed>, per operator (<username>) correction`. Existing revision lines are never rewritten.
36
+
37
+ ## Scope classes
38
+
39
+ Set at intake, applied as a label, announced with its reason (operator can override):
40
+
41
+ - **`research`** — a question to answer; throwaway code allowed, never merged. No branch/PR/changelog; findings + recommendation are the evidence comment.
42
+ - **`quick-build`** — small change and the flow being changed already exists in the repo to read. Brief (description) + plan (comment) are drafted in the same conversation; **one approval covers both**; then straight to `ready`.
43
+ - **`full-plan`** — big or new ground. Brief approval → `needs-plan` → a separate, fresh-grounded planning session posts the plan → `needs-operator` → "plan approved" → `ready`. Multi-deliverable work becomes an epic; each sub-issue is classified independently.
44
+
45
+ Scope calls are revisited through the one-way ratchet, whose rules and mechanics live in the `dev-plan` skill — the one home for upgrade/downgrade behavior.
46
+
47
+ ## Labels
48
+
49
+ State — exactly one per issue (creation colors live in dev-setup's labels row, their one home):
50
+
51
+ | label | meaning |
52
+ |---|---|
53
+ | `needs-operator` | waiting on the operator: a question, a brief or plan to approve, a proposal |
54
+ | `needs-plan` | brief approved; waiting for the planning stage (full-plan only) |
55
+ | `ready` | fully approved — an agent may start |
56
+ | `working` | claimed, in progress; the ledger comment shows live progress |
57
+ | `for-operator` | done — evidence posted, awaiting operator review |
58
+
59
+ Modifiers (may coexist with the state label): `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents, only where the org has no native Epic issue type).
60
+
61
+ ## Titles, types, hierarchy
62
+
63
+ - **Title prefixes** on issues, branches, and PRs identically: dev.md's `branch:` knob type list (that knob stays the list's one home) plus `research:` for research issues. PR title = issue title.
64
+ - **Native issue types** where the org defines them: Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (label fallback otherwise).
65
+ - **Hierarchy:** epic parent = map only (Destination · Decisions so far as one-line gists · Not clear yet · Out of scope), children attached as native sub-issues; issues = the unit of work (brief in description, own approvals/branch/PR/evidence); tasks = checkboxes **in the plan comment only**. Blockers use native issue dependencies; phases use milestones. Only issues — never epics — get `ready`. GitHub caps issue bodies and comments at ~65,536 characters; what a plan nearing that cap means is the `dev-plan` ratchet's call.
66
+
67
+ ## The ledger
68
+
69
+ Maintained by the implement session as one comment, edited in place:
70
+
71
+ ```markdown
72
+ <!-- vsk:v1 type=ledger branch=<branch> -->
73
+ ## Ledger — <branch>
74
+ - Task <N>: complete (commits <base7>..<head7>[, review clean | K parked])
75
+ - Task <N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
76
+ - Ruling: <what> — <why> — cost if wrong: <cost>
77
+ - Task <N>: parked — <finding> — Ruling: <why the code stands>
78
+ - Deferred minor: <one-liner>
79
+ ```
80
+
81
+ **Resume protocol:** a fresh, compacted, or (operator-handed) takeover session reads, in order: the brief → the plan comment → the ledger → `git log` on the branch — **nothing else**. Tasks with a `complete` line are DONE, never re-executed; a task whose last line is a fix round resumes at the next round. After compaction, trust the ledger and `git log` over recollection. Every `Ruling:` line surfaces in the evidence comment — a ruling that dies with the session was a decision made in secret.
82
+
83
+ ## `.vegastack/.tmp/` workspace
84
+
85
+ All transitory artifacts — subagent reports, review packages, plan drafts, extracted diffs — live at `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue intake drafts, which have no number yet: `.vegastack/.tmp/intake-<slug>/`), kept out of git by a self-ignoring `.gitignore` (`printf '*\n' > .vegastack/.tmp/.gitignore`, created on first use). Subagents write full reports to files there and return only short status — a dead subagent's findings survive on disk, and the primary session never holds full reports in context. The workspace lives in the working tree (never under `.git/`, which harnesses protect from writes).
86
+
87
+ ## Verification gate
88
+
89
+ Before claiming any status: **IDENTIFY** the command that proves the claim → **RUN** it fresh and complete → **READ** the full output and exit code → only then claim, with the evidence. "Should pass", a previous run, or a subagent's say-so are never evidence. Guard scripts follow the same doctrine: machine-verifiable facts **block** (exit 2 with the reason); regex or judgment heuristics only **warn** — no AI inference inside guards, and an unverifiable state fails closed.
90
+
91
+ ## Plain-language collaboration
92
+
93
+ Every skill run ends with a simple-language summary: what happened, which paths were taken — cross-agent invocations announced at trigger time AND summarized at the end — and what is worth the operator double-checking. Use mermaid or ASCII diagrams in issues wherever a picture beats prose. A vague or self-contradicting operator answer gets pushback with concrete options, never silent absorption.
@@ -0,0 +1,3 @@
1
+ # Refresh contract — dev-status
2
+
3
+ Evergreen: this skill asserts no version pins, numeric vendor limits, or dated claims — the gh CLI surfaces it shells to are the long-stable subcommands the family already treats as durable. Revisit if a future edit introduces a volatile fact.
@@ -0,0 +1,6 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "retrievalBaseline": "2026-08-28",
4
+ "note": "Evergreen waiver recorded in REFRESH.md; sources deliberately empty.",
5
+ "sources": []
6
+ }