@vegastack/vegafactory 0.19.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 (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +417 -0
  3. package/dist/dashboard-artifact.json +21240 -0
  4. package/dist/index.js +22752 -0
  5. package/dist/run-wrapper.js +377 -0
  6. package/package.json +46 -0
  7. package/skill/dev-architect/SKILL.md +106 -0
  8. package/skill/dev-architect/agents/openai.yaml +4 -0
  9. package/skill/dev-architect/references/ai-agents.md +96 -0
  10. package/skill/dev-architect/references/conventions.md +113 -0
  11. package/skill/dev-architect/references/data.md +89 -0
  12. package/skill/dev-architect/references/infra.md +99 -0
  13. package/skill/dev-architect/references/mobile.md +75 -0
  14. package/skill/dev-architect/references/pinned-facts.md +133 -0
  15. package/skill/dev-architect/references/principles.md +117 -0
  16. package/skill/dev-architect/references/security.md +90 -0
  17. package/skill/dev-architect/references/stack.md +38 -0
  18. package/skill/dev-architect/references/web.md +102 -0
  19. package/skill/dev-architect/refresh/REFRESH.md +31 -0
  20. package/skill/dev-architect/refresh/sources.json +239 -0
  21. package/skill/dev-chronicle/SKILL.md +52 -0
  22. package/skill/dev-chronicle/agents/openai.yaml +4 -0
  23. package/skill/dev-chronicle/references/conventions.md +113 -0
  24. package/skill/dev-chronicle/references/styles.md +75 -0
  25. package/skill/dev-chronicle/refresh/REFRESH.md +3 -0
  26. package/skill/dev-chronicle/refresh/sources.json +6 -0
  27. package/skill/dev-debug/SKILL.md +43 -0
  28. package/skill/dev-debug/agents/openai.yaml +4 -0
  29. package/skill/dev-debug/references/conventions.md +113 -0
  30. package/skill/dev-debug/references/loop-ladder.md +20 -0
  31. package/skill/dev-debug/refresh/REFRESH.md +3 -0
  32. package/skill/dev-debug/refresh/sources.json +6 -0
  33. package/skill/dev-implement/SKILL.md +81 -0
  34. package/skill/dev-implement/agents/openai.yaml +4 -0
  35. package/skill/dev-implement/assets/workflows/implement-children.js +12 -0
  36. package/skill/dev-implement/references/ask-route.md +80 -0
  37. package/skill/dev-implement/references/changelog-and-chronicle.md +21 -0
  38. package/skill/dev-implement/references/conventions.md +113 -0
  39. package/skill/dev-implement/references/ledger-and-resume.md +52 -0
  40. package/skill/dev-implement/references/parallel-children.md +35 -0
  41. package/skill/dev-implement/references/worktrees.md +63 -0
  42. package/skill/dev-implement/refresh/REFRESH.md +3 -0
  43. package/skill/dev-implement/refresh/sources.json +6 -0
  44. package/skill/dev-implement/scripts/children.mjs +479 -0
  45. package/skill/dev-implement/scripts/effective-policy.mjs +694 -0
  46. package/skill/dev-implement/scripts/evidence-check.mjs +107 -0
  47. package/skill/dev-implement/scripts/evidence-upload.mjs +181 -0
  48. package/skill/dev-implement/scripts/learning.mjs +41 -0
  49. package/skill/dev-implement/scripts/lib/approval.mjs +1182 -0
  50. package/skill/dev-implement/scripts/lib/gh.mjs +101 -0
  51. package/skill/dev-implement/scripts/preflight.mjs +153 -0
  52. package/skill/dev-implement/scripts/questions.mjs +381 -0
  53. package/skill/dev-implement/scripts/reclaim.mjs +116 -0
  54. package/skill/dev-implement/scripts/recovery.mjs +213 -0
  55. package/skill/dev-implement/scripts/worktree.mjs +991 -0
  56. package/skill/dev-intake/SKILL.md +80 -0
  57. package/skill/dev-intake/agents/openai.yaml +4 -0
  58. package/skill/dev-intake/references/ask-route.md +80 -0
  59. package/skill/dev-intake/references/brief-template.md +89 -0
  60. package/skill/dev-intake/references/conventions.md +113 -0
  61. package/skill/dev-intake/refresh/REFRESH.md +3 -0
  62. package/skill/dev-intake/refresh/sources.json +6 -0
  63. package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
  64. package/skill/dev-intake/scripts/lib/approval.mjs +1182 -0
  65. package/skill/dev-intake/scripts/questions.mjs +381 -0
  66. package/skill/dev-plan/SKILL.md +54 -0
  67. package/skill/dev-plan/agents/openai.yaml +4 -0
  68. package/skill/dev-plan/references/ask-route.md +80 -0
  69. package/skill/dev-plan/references/conventions.md +113 -0
  70. package/skill/dev-plan/references/plan-format.md +82 -0
  71. package/skill/dev-plan/refresh/REFRESH.md +3 -0
  72. package/skill/dev-plan/refresh/sources.json +6 -0
  73. package/skill/dev-plan/scripts/lib/approval.mjs +1182 -0
  74. package/skill/dev-plan/scripts/plan-lint.mjs +319 -0
  75. package/skill/dev-plan/scripts/questions.mjs +381 -0
  76. package/skill/dev-review/SKILL.md +76 -0
  77. package/skill/dev-review/agents/openai.yaml +4 -0
  78. package/skill/dev-review/assets/review-known-patterns.md.template +32 -0
  79. package/skill/dev-review/references/conventions.md +113 -0
  80. package/skill/dev-review/references/cross-agent.md +39 -0
  81. package/skill/dev-review/references/dispatch-prompts.md +121 -0
  82. package/skill/dev-review/references/security-axis.md +45 -0
  83. package/skill/dev-review/refresh/REFRESH.md +5 -0
  84. package/skill/dev-review/refresh/sources.json +6 -0
  85. package/skill/dev-setup/SKILL.md +113 -0
  86. package/skill/dev-setup/agents/openai.yaml +4 -0
  87. package/skill/dev-setup/assets/agents-section.md.template +24 -0
  88. package/skill/dev-setup/assets/dev-profile.md.template +102 -0
  89. package/skill/dev-setup/assets/factory-board.yml.template +162 -0
  90. package/skill/dev-setup/assets/hooks/decision-nudge.mjs +30 -0
  91. package/skill/dev-setup/assets/hooks/prompt-skill-mention.mjs +29 -0
  92. package/skill/dev-setup/assets/hooks/session-end.mjs +14 -0
  93. package/skill/dev-setup/assets/hooks/session-start.mjs +178 -0
  94. package/skill/dev-setup/assets/hooks/ship-guard.mjs +738 -0
  95. package/skill/dev-setup/assets/hooks/skill-activated.mjs +47 -0
  96. package/skill/dev-setup/assets/hooks/stop-heartbeat.mjs +14 -0
  97. package/skill/dev-setup/assets/workflows/implement-children.js +12 -0
  98. package/skill/dev-setup/references/ask-route.md +80 -0
  99. package/skill/dev-setup/references/conventions.md +113 -0
  100. package/skill/dev-setup/references/github-app.md +286 -0
  101. package/skill/dev-setup/references/harness-facts.md +169 -0
  102. package/skill/dev-setup/references/stack-playbooks.md +124 -0
  103. package/skill/dev-setup/refresh/REFRESH.md +13 -0
  104. package/skill/dev-setup/refresh/sources.json +602 -0
  105. package/skill/dev-setup/scripts/effective-policy.mjs +694 -0
  106. package/skill/dev-setup/scripts/questions.mjs +381 -0
  107. package/skill/dev-setup/scripts/ship-policy.mjs +195 -0
  108. package/skill/dev-ship/SKILL.md +56 -0
  109. package/skill/dev-ship/agents/openai.yaml +4 -0
  110. package/skill/dev-ship/references/conventions.md +113 -0
  111. package/skill/dev-ship/references/runbook.md +72 -0
  112. package/skill/dev-ship/refresh/REFRESH.md +3 -0
  113. package/skill/dev-ship/refresh/sources.json +6 -0
  114. package/skill/dev-ship/scripts/lib/approval.mjs +1182 -0
  115. package/skill/dev-ship/scripts/ship-gate.mjs +485 -0
  116. package/skill/dev-status/SKILL.md +56 -0
  117. package/skill/dev-status/agents/openai.yaml +4 -0
  118. package/skill/dev-status/references/conventions.md +113 -0
  119. package/skill/dev-status/refresh/REFRESH.md +3 -0
  120. package/skill/dev-status/refresh/sources.json +6 -0
  121. package/skill/dev-status/scripts/effective-policy.mjs +694 -0
  122. package/skill/dev-status/scripts/status.mjs +311 -0
  123. package/skill/skill-maintainer/SKILL.md +82 -0
  124. package/skill/skill-maintainer/agents/openai.yaml +4 -0
  125. package/skill/skill-maintainer/references/release-ops.md +61 -0
  126. package/skill/skill-maintainer/references/standards.md +137 -0
  127. package/skill/skill-maintainer/refresh/REFRESH.md +40 -0
  128. package/skill/skill-maintainer/refresh/sources.json +103 -0
  129. package/skill/skill-scan/SKILL.md +59 -0
  130. package/skill/skill-scan/agents/openai.yaml +4 -0
  131. package/skill/skill-scan/refresh/REFRESH.md +18 -0
  132. package/skill/skill-scan/refresh/sources.json +133 -0
  133. package/skill/skill-scan/scripts/lib/skillspector.mjs +226 -0
  134. package/skill/skill-scan/scripts/skill-scan.mjs +1002 -0
  135. package/skill/skillify/SKILL.md +108 -0
  136. package/skill/skillify/agents/openai.yaml +4 -0
  137. package/skill/skillify/assets/templates/README.md.template +26 -0
  138. package/skill/skillify/assets/templates/REFRESH.md.template +16 -0
  139. package/skill/skillify/assets/templates/SKILL.md.template +27 -0
  140. package/skill/skillify/assets/templates/evals.json.template +12 -0
  141. package/skill/skillify/assets/templates/openai.yaml.template +4 -0
  142. package/skill/skillify/assets/templates/skill.test.ts.template +27 -0
  143. package/skill/skillify/assets/templates/sources.json.template +6 -0
  144. package/skill/skillify/assets/templates/trigger-queries.json.template +1 -0
  145. package/skill/skillify/references/authoring.md +103 -0
  146. package/skill/skillify/references/eval-playbook.md +112 -0
  147. package/skill/skillify/refresh/REFRESH.md +23 -0
  148. package/skill/skillify/refresh/sources.json +6 -0
  149. package/skill/skillify/scripts/scaffold-skill.mjs +334 -0
  150. package/skill/skillify/scripts/trigger-check.mjs +209 -0
  151. package/skill/vegafactory-setup/SKILL.md +77 -0
  152. package/skill/vegafactory-setup/agents/openai.yaml +4 -0
  153. package/skill/vegafactory-setup/assets/control-room/boards.md.template +17 -0
  154. package/skill/vegafactory-setup/assets/control-room/decisions.md.template +5 -0
  155. package/skill/vegafactory-setup/assets/control-room/group.md.template +44 -0
  156. package/skill/vegafactory-setup/assets/control-room/onboarding/dispatcher-box.md.template +86 -0
  157. package/skill/vegafactory-setup/assets/control-room/onboarding/new-repo.md.template +13 -0
  158. package/skill/vegafactory-setup/assets/control-room/onboarding/new-teammate.md.template +12 -0
  159. package/skill/vegafactory-setup/assets/control-room/org.md.template +60 -0
  160. package/skill/vegafactory-setup/assets/control-room/people.csv.template +2 -0
  161. package/skill/vegafactory-setup/assets/control-room/repos.md.template +7 -0
  162. package/skill/vegafactory-setup/assets/control-room/rules/CODEOWNERS.template +6 -0
  163. package/skill/vegafactory-setup/assets/control-room/rules/README.md.template +9 -0
  164. package/skill/vegafactory-setup/assets/control-room/rules/stats-privacy.md.template +44 -0
  165. package/skill/vegafactory-setup/assets/control-room/templates/README.md.template +9 -0
  166. package/skill/vegafactory-setup/references/control-room.md +149 -0
  167. package/skill/vegafactory-setup/references/conventions.md +113 -0
  168. package/skill/vegafactory-setup/refresh/REFRESH.md +5 -0
  169. package/skill/vegafactory-setup/refresh/sources.json +6 -0
  170. package/skill-integrity.json +252 -0
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: dev-intake
3
+ description: Turn ideas, brainstorms, feature requests, bug reports, or SOW documents into GitHub issues an agent can act on without further questions. Use when the user asks for a new feature or capability ("add support for X", "I need Y", "can we make it do Z"), when asked to "turn this into issues", "create tasks from this SOW", "write up an issue for" a feature or bug, "users report X — make an issue", "plan this as issues", "slice this epic", or when the user gives approval on a drafted issue and it needs recording. Not for writing the implementation plan of an approved issue (dev-plan), implementing issues or a trivial one-or-two-file fix (dev-implement), creating PRs or merging (dev-ship), or project bootstrap (dev-setup).
4
+ ---
5
+
6
+ # dev-intake
7
+
8
+ Write the issue: every question is asked here, because dark mode asks none.
9
+
10
+ Requirements come in as the operator's brainstorm, feature thought, bug report, or SOW; issues go out complete enough that a fresh agent needs nothing but the URL, because an under-specified issue becomes an interruption or a guess.
11
+
12
+ Nearest neighbors: `dev-plan` owns the how once a brief is approved; intake owns the what/why and the approval mechanics; `dev-implement` builds.
13
+
14
+ ## Ground before you ask
15
+
16
+ Finding facts is your job, because a brief built on unverified facts is a confident mistake waiting for dark mode. Before the first question:
17
+
18
+ - **Read the file before speaking about it** — open the actual paths the work would change: current behavior, patterns to reuse, where it plugs in. The brief cites these real paths later, because a brief naming no files is a sign this step was skipped.
19
+ - Verify dependencies: any library, service, or API capability the approach leans on gets checked against current official docs, noted with the date; stack, schema, auth, and infra choices route through `dev-architect`'s verify protocol.
20
+ - Cross-check the request against product docs and current behavior; a contradiction is asked out loud — "you asked for X; the code does Y — which wins?" — because a silently resolved contradiction is a guess the operator did not make. Push back on cost the same way: when a simpler version covers most of the need, name it.
21
+ - Triage every unknown into three bins: *findable* → find it now, yourself; *only-the-operator-knows* → ask, with a recommendation; *only-running-code-can-tell* → a `research` issue or the issue's first spike step. Guessing is not a bin.
22
+
23
+ ## Scope the work — say it out loud
24
+
25
+ Every issue gets one scope call, announced with its reason, applied as a label, and recorded in the brief's `**Scope:**` line so the reasoning survives the conversation; the operator can override it:
26
+
27
+ - **`research`** — a question to answer, not code to keep. The brief is the question plus what "answered" looks like.
28
+ - **`quick-build`** — the objective test (conventions' wording): *a small change and the flow being changed already exists in the repo to read*. Missing either half means it is not quick-build; familiarity with the kind of app doesn't count.
29
+ - **`full-plan`** — big or new ground: a new subsystem, a restructuring, a brand-new flow.
30
+
31
+ When the two halves of the test disagree, or the class is unclear, take the heavier one, because the ratchet only ever goes up. Re-classification after this point belongs to `dev-plan`'s one-way ratchet, and a downgrade waits for the operator's yes.
32
+
33
+ ## The interview
34
+
35
+ Ask in rounds by the ask route (`references/ask-route.md`): your harness's question tool when you have one and the asker is the issue's operator, otherwise one `questions` comment on the issue and `needs-operator`, because a headless run that cannot ask is not a run that may guess. On that issue route, create the issue before the first round — `needs-operator`, the operator assigned, the request as its body — so the round has a surface; the brief replaces that body once the round is answered. Each round covers the current frontier, every open decision that doesn't depend on another answer. Number the questions; give each a recommended answer with a one-line reason so the operator can reply "all recommended", and skip what the material or an earlier round settled, because a re-asked question reads as not having listened. A vague or self-contradicting answer gets pushback with concrete options — a mermaid or ASCII sketch when a picture beats prose — because a vague answer absorbed silently becomes a guess in dark mode. Stop when *a fresh agent could act on each issue without asking anything.*
36
+
37
+ The angles, in order — product (who, observable outcome, in/out of scope, slices, priority) → behavior (flows, rules, permissions, edge and failure cases; UI states and copy) → technical (only choices genuinely the operator's, each with a recommendation, checked against `dev-architect`; the version impact where the project versions releases) → quality and risk (what proves it works, what earns `risky`, what stops a dark run). Deep approach trade-offs beyond the operator's choices belong to `dev-plan`. Where dev.md's `issue-fields:` knob names org fields, two of the numbered questions are Priority and Effort, their options read once from `gh api orgs/<org>/issue-fields` and ordered by each option's `priority` key rather than guessed — recommend the option named `Medium` for Priority, or the middle option where the org names none, and for Effort the lowest option on `research` and `quick-build`, the middle option on `full-plan` — so "all recommended" still answers both, and a knob at `none` skips them.
38
+
39
+ **Bug variant** (`fix:` issues): reproduction steps — or the artifacts needed to obtain them (logs, HAR, recording) — are a required brief section, the brief names `dev-debug` as the implement path, and a bug that can't be reproduced yet becomes a `research` issue first.
40
+
41
+ ## Slicing and hierarchy
42
+
43
+ - One issue = one outcome that fits one agent session, sliced vertically; blockers use native dependencies, phases milestones, parents native sub-issues.
44
+ - Deliberately deferred work ("someday, not now") lives in the parent's out-of-scope section, because an icebox issue clutters the tracker; a tracking issue exists only on the operator's ask.
45
+ - **Epics:** a multi-deliverable feature gets a parent whose body is a map, because a parent that is also work gets claimed — `Destination` (the one or two lines every session orients to) · `Decisions so far` (one-line gists linking closed children) · `Not clear yet` (in-scope questions you cannot yet phrase sharply — the test is phrasing, not answering; don't pre-slice fog) · `Out of scope` (the tempting adjacent work, named). Each child is classified independently. Only children get `ready`, because the epic is the map.
46
+ - Titles carry the type prefix (dev.md `branch:` type list + `research:`) and the native issue type where the org has them; issue, branch, and PR agree.
47
+
48
+ ## The brief
49
+
50
+ The issue body follows [brief-template](references/brief-template.md), marker line included: inline over linked, concrete over abstract, evidence over confidence — touch points name real paths, dependency claims carry their check date, and anything unverifiable goes to **Assumptions — confirm or correct**, because an asserted guess binds the agent. Tests-and-acceptance names the seams — the public boundaries tests will live at — because dark mode can't ask later. A brief runs 300–600 words: a section the fresh agent would not need is cut, and one they would have to guess at is missing.
51
+
52
+ Quick-build issues get their plan now: after the brief has consensus, invoke `dev-plan`'s inline mode in this conversation and post brief (description) + plan (comment) together, so the operator's single approval covers both.
53
+
54
+ Before posting any brief, run `node <path-to-this-skill>/scripts/brief-lint.mjs --file <draft> --scope <class> --json` (add `--fix` for fix:-type briefs — it requires the Reproduction section): structure gaps block (exit 2), quality smells warn; fix blocks before the operator sees the draft. Inline plans also pass `dev-plan`'s plan-lint.
55
+
56
+ ## Labels and approval
57
+
58
+ - A new issue starts at `needs-operator` plus its scope label, and `risky` when it touches security, money, user data, or production (names from dev.md's `labels:` knob); create it with `--assignee <operator>`, the login conventions' Labels table resolves from dev.md's `operators:` list, so GitHub's own notification reaches the human whose move it is. An `--assignee` GitHub rejects is reported and the issue stands unassigned, because guessing another login hands the work to the wrong person.
59
+ - Creation also stamps the native type where dev.md's `issue-types:` knob names one for the issue's title prefix — `gh issue create --type <Name>` at gh 2.94.0 and above, otherwise `gh api -X PATCH repos/{owner}/{repo}/issues/{n} -f type=<Name>` in the same breath as creation — and both fields where `issue-fields:` names them, in one request, because the PUT replaces every value it does not carry:
60
+
61
+ ```sh
62
+ gh api "orgs/$ORG/issue-fields" --jq '.[] | select(.name=="Priority" or .name=="Effort") | {id, name}' # once per run
63
+ printf '{"issue_field_values":[{"field_id":%s,"value":"%s"},{"field_id":%s,"value":"%s"}]}' \
64
+ "$PRIORITY_ID" "$PRIORITY" "$EFFORT_ID" "$EFFORT" |
65
+ gh api -X PUT "repos/$OWNER/$REPO/issues/$N/issue-field-values" --input -
66
+ gh api "repos/$OWNER/$REPO/issues/$N" --jq .type.name # read the type back
67
+ gh api "repos/$OWNER/$REPO/issues/$N/issue-field-values" # read the values back
68
+ ```
69
+
70
+ GitHub drops a type or a field value written without push access and returns success, so the two readbacks decide the claim and a mismatch is reported rather than assumed away. Both knobs at `none` — a personal repo, or an org defining neither — means the issue carries its labels and nothing else; say that in one plain sentence instead of reporting a failure.
71
+ - Approval is the operator's explicit words tied to the issue, because labels, silence and time say nothing about consent.
72
+ - Record one schema-v2 approval event per conventions: `scope=brief`, or `scope=brief+plan` for brief plus plan comment. Use bundled `scripts/lib/approval.mjs`’s `artifactRef` on refreshed canonical artifacts; include actual operator words and artifact bindings. Session attestations require a policy-operator publisher; other recorders may only relay an independently verified identical scoped grant per conventions. Evaluate fresh complete history/current policy, preserving canonical `approvalBindings`. Preserve legacy records for scoped reconfirmation; a marker alone grants nothing.
73
+ - Then flip the state, carrying the assignee the Labels table names: `research` and `quick-build` → `ready` (unassigned); `full-plan` → `needs-plan` (the operator).
74
+ - An issue leaves `needs-operator` only once every Assumptions entry is resolved (confirmed, corrected, or moved to a spike) and the section deleted.
75
+ - A directional decision this work settles (dev.md's Decisions test) is proposed as one register line on the operator's yes; `dev-ship` records at merge.
76
+ - The operator edits a draft → apply it and summarize what changed since they last read it.
77
+
78
+ ## After approval
79
+
80
+ An approved issue that later needs a material change flips back to `needs-operator` with one comment naming what changed; the new approval is recorded the same way and the brief's revision marker bumps. Only the canonicalizer’s specified progress fields preserve approval; every other scope-byte edit requires refreshed intent.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "dev-intake"
3
+ short_description: "Turn ideas or SOWs into agent-ready GitHub issues"
4
+ default_prompt: "Use $dev-intake to turn this into GitHub issues."
@@ -0,0 +1,80 @@
1
+ # The ask route
2
+
3
+ Where a round of questions goes when a skill needs the user. Two surfaces: the harness's question tool, or the issue itself. This file is the one home for the route, the comment shape and the reply grammar; `scripts/questions.mjs` is the deterministic method behind them, and the marker row lives in [conventions](conventions.md).
4
+
5
+ ## The route
6
+
7
+ Three steps, in this order, first match wins:
8
+
9
+ 1. `VSK_ASK_ROUTE` is set to `issue` or `tool` — the dispatcher and CI set it; any other non-empty value is refused rather than guessed.
10
+ 2. This harness and this run have no question tool → `issue`.
11
+ 3. The asker is not the issue's operator → `issue`. An unresolved asker or operator is also `issue`.
12
+
13
+ Otherwise the tool. The issue route needs an issue: where none exists yet — dev-intake's interview runs before its issue is created — the skill creates the issue first, at `needs-operator` with the operator assigned and the request as its body, and posts the round to it; the brief is written into that issue once the round is answered. On the tool route the issue is created after approval, as before. Settle it deterministically rather than by judgement:
14
+
15
+ ```sh
16
+ node <path-to-this-skill>/scripts/questions.mjs route --tool <name|none> --asker <login> --operator <login> --json
17
+ ```
18
+
19
+ Which tool each harness has — and the Codex Plan-mode gating on `request_user_input` — is recorded in dev-setup's `references/harness-facts.md` (a backticked path, not a link: this file ships into dev-intake, dev-plan and dev-implement, which do not carry that reference) and not restated here. The operator identity comes from the caller under dev.md's `operators:` knob; the script takes both logins as inputs and never resolves them itself.
20
+
21
+ The bias is deliberate: a round in a comment is always readable by whoever owns the issue, and a round put to the wrong person is not.
22
+
23
+ ## The comment
24
+
25
+ One comment per round, marker first, the whole round wrapped in `<questions>` tags so the parser and the model both find it inside a comment that may carry prose around it:
26
+
27
+ ```markdown
28
+ <!-- vsk:v1 type=questions rev=1 -->
29
+ ## Questions (v1)
30
+
31
+ <questions>
32
+ **Q1.** Where does the reminder queue live?
33
+ - a) A Postgres table
34
+ - b) A Redis list (recommended — Redis is already a dependency)
35
+
36
+ **Q2.** How late may a reminder fire?
37
+ - a) Within the hour (recommended — matches the existing cron cadence)
38
+ - b) Same day
39
+
40
+ Reply with `1: a` per question, or `all recommended`.
41
+ </questions>
42
+ ```
43
+
44
+ No question, option or reason may carry an HTML comment delimiter or a `questions` block tag: a round can be read back out of a comment anyone may have written, so text that could close the block or forge a marker is refused in both directions. Every question carries at least two options and exactly one recommendation, and every recommendation carries its one-line reason — a round that cannot say which way it leans is a round that has not been thought through, and the renderer refuses it. Options run `a` through `h`. After posting, the label moves to `needs-operator` and the session ends.
45
+
46
+ ## Replying
47
+
48
+ Anyone on the issue may answer, in an ordinary comment, one line per question:
49
+
50
+ - `1: b`
51
+ - `2: a — the cron already runs` (trailing prose after the dash is kept)
52
+ - `3: other — a third way` (`other` is accepted for any question)
53
+ - `all recommended` on its own line fills every question not answered explicitly
54
+
55
+ An explicit line always beats `all recommended`. Bulleted lines, a `.` instead of `:`, and upper-case letters all parse. Surrounding prose is ignored; the first answer to a question stands and a repeat is reported. A numbered line whose letter runs straight into prose with no dash (`1: a is wrong, go with b`) is malformed, not an answer of `a` — the parser reports it and the question is re-asked.
56
+
57
+ ## Re-asks
58
+
59
+ Parse before asking anything. A later session has no `round.json` on disk, so it reads the round back out of the posted comment — that is what the `<questions>` wrapper is for, and `--round <comment.md>` takes it in place of `--spec`. What comes back is answered questions, still-open questions, and malformed lines. If nothing is open, continue — never re-ask an answered question. If something is open, post a second comment at `rev=<n+1>` carrying only the open questions **at their original numbers**, so `**Q3.**` stays Q3. Earlier `questions` comments are left in place as record. A reply with no answer line at all is malformed, not empty: it gets one re-ask naming the expected shape.
60
+
61
+ ## What it is not
62
+
63
+ An answer is not an approval. Any teammate may answer a round; only the operator approves, and approval is still its own `approval` marker comment recording the operator's own words in the `(<username>)` format ([conventions](conventions.md)). A round that is fully answered unblocks the work; it does not move the issue to `ready`.
64
+
65
+ Assignment is not this route's job either — the label moving to `needs-operator` is what puts the issue on the operator.
66
+
67
+ ## Commands
68
+
69
+ Save the reply comment to `.vegastack/.tmp/<issue>-<slug>/reply.md` first; the parser reads a file, never a network.
70
+
71
+ ```sh
72
+ node <path-to-this-skill>/scripts/questions.mjs render --spec round.json --rev 1 --json
73
+ node <path-to-this-skill>/scripts/questions.mjs parse --comment reply.md --round asked.md --json
74
+ node <path-to-this-skill>/scripts/questions.mjs re-ask --round asked.md --comment reply.md --rev 2 --json
75
+ node <path-to-this-skill>/scripts/questions.mjs route --tool none --asker <login> --operator <login> --json
76
+ ```
77
+
78
+ `asked.md` is the posted `questions` comment; `--spec round.json` takes the same round as JSON instead, where the rendering session still has it. A spec is `{ "questions": [ { "text": "…", "options": [ { "letter": "a", "text": "…" }, { "letter": "b", "text": "…", "recommended": true, "reason": "…" } ] } ] }`.
79
+
80
+ Exit codes: 0 pass · 1 answers still open or malformed, and for `re-ask` nothing left to ask · 2 refusal or usage error.
@@ -0,0 +1,89 @@
1
+ # Issue brief template
2
+
3
+ The issue body a workable issue must have. Write the sections that apply, delete the rest. The test for every section: would a fresh agent have to guess or ask without it?
4
+
5
+ ```markdown
6
+ <!-- vsk:v1 type=brief rev=1 scope=research|quick-build|full-plan -->
7
+ **Scope:** research | quick-build | full-plan — the announced reason for the call, one line.
8
+ **Priority:** <one of the org's Priority options> — the answer from the interview. Delete this line where dev.md's `issue-fields:` knob is `none`.
9
+ **Effort:** <one of the org's Effort options> — the answer from the interview. Delete this line where the knob is `none`.
10
+
11
+ ## Outcome
12
+
13
+ What exists when this is done, in observable terms — what the user can do, what the
14
+ system produces. One paragraph.
15
+
16
+ Research issues replace Outcome and the build sections with two headings brief-lint
17
+ expects verbatim in spirit: `## The question` (what this issue resolves) and
18
+ `## What answered looks like` (the evidence that closes it). Risks/stop conditions
19
+ and Assumptions still apply.
20
+
21
+ ## Out of scope
22
+
23
+ The nearby things this issue deliberately does NOT do. This is what stops scope creep
24
+ in dark mode — name the tempting adjacent work.
25
+
26
+ ## Rules and edge cases
27
+
28
+ The behavior that isn't obvious: validations, permissions, limits, empty/error/concurrent
29
+ cases, what happens on failure. Bullet list, one behavior per line.
30
+
31
+ ## Reproduction <!-- fix: issues only -->
32
+
33
+ The exact steps (or attached artifacts — logs, HAR, recording) that demonstrate the
34
+ bug today, and the observed vs expected behavior. A bug without this is a `research`
35
+ issue, not a fix. The implement path is dev-debug.
36
+
37
+ ## UI states <!-- only when there is UI -->
38
+
39
+ Loading, empty, error, success, disabled. Which design-system components. Copy for
40
+ user-facing text. Responsive and keyboard behavior when it matters.
41
+
42
+ ## Approach and touch points
43
+
44
+ The chosen technical approach in a few lines: which parts of the codebase change,
45
+ new/changed interfaces or schemas, data migrations. Routine choices stay the
46
+ implementer's — don't specify them. Name the docs and changelog surfaces this change
47
+ must update. Task-level detail belongs to the plan (dev-plan), not here.
48
+ **Version impact:** patch | minor | major, one-line reason — only when the project
49
+ versions releases (dev.md `changelog:` knob).
50
+
51
+ ## Tests and acceptance
52
+
53
+ What proves it works: the cases tests must cover (success, boundary, failure,
54
+ authorization where relevant), the commands to run, and the **seams** — the public
55
+ boundaries tests live at (dark mode can't negotiate seams later; they're settled
56
+ here). Acceptance = the Outcome plus these passing.
57
+
58
+ ## Risks and stop conditions
59
+
60
+ What could go wrong and what should make the agent stop and ask instead of pushing
61
+ through — beyond the standing stop-list in .vegastack/dev.md.
62
+
63
+ ## Assumptions — confirm or correct
64
+
65
+ Anything material the grounding investigation could not verify, one per line, each
66
+ awaiting the operator's confirm/correct. The issue cannot leave needs-operator while
67
+ one is unconfirmed. Verified facts never appear here — they live in their section
68
+ with their evidence. Delete the whole section once every entry is resolved (its
69
+ presence alone blocks preflight).
70
+ ```
71
+
72
+ ## Writing rules
73
+
74
+ - Inline over linked: the material details live in the issue itself. A link supports; it never substitutes.
75
+ - Concrete over abstract: "rejects amounts over 10,000 with error E402" beats "validates input".
76
+ - Evidence over confidence: touch points name real file paths; a dependency capability claim carries the doc check and its date; what couldn't be verified goes to Assumptions, never stated as fact.
77
+ - The brief binds the agent, so ambiguity is a bug in the brief — if two readings exist, the interview wasn't done.
78
+ - Post-approval edits follow the revision-marker rule in dev-setup's `references/conventions.md` (heading `(v2)`, marker `rev=2`, a `Revisions:` line).
79
+ - A `Decision:` comment exists only for a choice that passes the Decisions test in `.vegastack/dev.md` — feature requests and implementation details never qualify; they are brief content, not register lines.
80
+
81
+ ### Summarising an SOW
82
+
83
+ The brief restates the SOW in the agent's own words and quotes only the terms the client owns — dates, amounts, defined deliverables — so a reader can tell our reading from their commitment:
84
+
85
+ <example>
86
+ SOW excerpt: "Vendor shall deliver a customer portal supporting invoice download (PDF), payment status, and dispute submission within 60 days of kickoff."
87
+
88
+ Outcome, in the brief: A signed-in customer opens their portal, downloads any invoice as a PDF, sees whether it is paid, and files a dispute against it. The SOW commits to delivery "within 60 days of kickoff" — quoted, because the date is the client's term and not ours to soften. "Dispute submission" is quoted because the SOW does not say what a dispute contains; that gap is the first line under Assumptions — confirm or correct.
89
+ </example>
@@ -0,0 +1,113 @@
1
+ # Workflow conventions
2
+
3
+ Artifact authority.
4
+
5
+ Defaults resolve repo, group, then org; locks require explicit org delegation. Repository dispatch/commands never inherit; registers concatenate. Policy/migration uses dev-setup's `scripts/effective-policy.mjs` and vegafactory-setup's control-room reference.
6
+
7
+ ## Comment metadata markers
8
+
9
+ Comments open:
10
+
11
+ ```markdown
12
+ <!-- vsk:v1 type=<type> rev=<n> [key=value ...] -->
13
+ ## <Human title> (v<n>)
14
+ ```
15
+
16
+ | type | required keys | instances |
17
+ |---|---|---|
18
+ | `approval` | `scope=<brief\|brief+plan\|plan\|consolidated\|none>` and schema-v2 JSON | one per approval event |
19
+ | `questions` | `rev` | one per ask round; earlier rounds stay as record (dev-setup's `references/ask-route.md`) |
20
+ | `plan` | `rev` | one, edited in place |
21
+ | `ledger` | `branch` | one, edited in place |
22
+ | `evidence` | `rev branch sha` | one, edited in place |
23
+ | `review` | `round sha agent=<claude\|codex> verdict=<clean\|needs-fixes>` | one per review cycle, rounds appended inside |
24
+ | `decision` | — | one per decision proposal |
25
+ | `handback` | — | one per stop event |
26
+
27
+ `rev=<n>` and `(v<n>)` start at 1 only on brief, plan, questions and evidence; other types have neither. Locate by marker, never heading/legacy fallback.
28
+
29
+ ## Operator identity
30
+
31
+ Use parenthesized GitHub usernames:
32
+
33
+ - Approval: `Approved by (<username>) on DD-MM-YYYY: "<their words>"`
34
+ - Register line: `- DD-MM-YYYY (<username>) — <decision>`
35
+
36
+ Approval.mjs’s publisher/relay contract lets current-policy provider-envelope publishers attest listed operators’ session words. Other recorders may only relay independently read identical operator-published scoped grants within complete authority history, without lifecycle mutations. Relays inherit source authority/lifecycle; account attestation cannot authenticate off-platform speech.
37
+
38
+ ## Scoped approval records
39
+
40
+ Use only dev-implement’s `scripts/lib/approval.mjs` and follow its contract. Refresh current policy and complete GitHub histories. `ArtifactRef={repo,issue,kind,artifactId,rev,digest}` binds brief issue-node or unique plan/protocol comment-node identity, revision and canonical SHA-256.
41
+
42
+ Post exactly one approval comment: matching scope marker, then one fenced JSON `ApprovalRecord={schemaVersion:2,id,operator,scope,source:{kind,ref,quote},artifacts,supersedes,revokes}`. Exclude outer Markdown fences, future alternatives and unresolved source locators; validate the whole body with approval.mjs's `parseApproval`. Source kind is `session` or `github-comment`, with inspectable words. Reuse valid current grants/relays; avoid counterfactual plan-only or redundant approvals. Scope is `brief`, `plan` or `brief+plan`; planning requires brief, implementation both, research execution also its protocol. Empty-artifact revocations remove exact earlier IDs. Conflicts explicitly supersede; newest never wins.
43
+
44
+ Preserve legacy comments. Without writes, inventory refusals/current digests and request reconfirmation. For duplicate canonical plans preserve both identities/bodies and request record-preserving reconciliation; never delete to clear ambiguity. Follow approval.mjs’s exact correction schema, operator-publisher and target checks. Only malformed or demonstrably invalid-source targets qualify, never valid authority or unavailable/inconsistent facts. Resolve source facts first; corrections grant no scope. Exact child checkpoint actions bind one selected code child's branch/ref/base/tasks/files; other actions never substitute.
45
+
46
+ Consolidated parent events bind frozen manifests, canonical artifacts and exact task/action subsets. Use inline UTF-8 or immutable repository/commit/path plus blob hash, never local paths. Canonical `approvalBindings` authorize; requested `recordBinding` only audits. Follow approval.mjs’s preparation/research/recovery provenance, receipts, adapters, counted attempts and fresh admission; retain immutable history and unverified legacy records. Keep checkpoint/private/live/shipping gates separate.
47
+
48
+ Canonicalization normalizes CRLF; its only exceptions are structural plan checkboxes and one validated JSON `{tasks:[{id,evidenceUrls}]}` block between `<!-- vsk:progress:start -->` / `<!-- vsk:progress:end -->`. IDs must exist; URLs are HTTP(S); unknown fields/duplicates refuse. Stable task IDs/order, interfaces, actions, revisions and all other bytes remain scope. Brief/protocol bodies have no mutable fields; fenced examples stay immutable and grant no authority.
49
+
50
+ ## Revision markers
51
+
52
+ Scope edits increment marker/heading revisions and append `Revisions: v2 — DD-MM-YYYY: <change>, per (<username>) correction`; preserve earlier lines and obtain fresh approval. Validated progress changes need neither.
53
+
54
+ ## Scope classes
55
+
56
+ Intake explains scope; operator overrides:
57
+
58
+ - **`research`** — inquiry; throwaway code allowed, never merged. No branch/PR/changelog; evidence comment contains findings and recommendation.
59
+ - **`quick-build`** — existing flow: draft brief+plan together, approve both, then `ready`.
60
+ - **`full-plan`** — new ground: approve brief, `needs-plan`, separate grounded planning session, `needs-operator`, approve plan, `ready`. Split multiple deliverables into independently classified epic children.
61
+
62
+ Scope ratchet: `dev-plan`.
63
+
64
+ ## Labels
65
+
66
+ One state; flips set assignees (colors: dev-setup):
67
+
68
+ | label | meaning | assignee |
69
+ |---|---|---|
70
+ | `needs-operator` | question, brief or plan approval, proposal | the operator |
71
+ | `needs-plan` | brief approved; awaiting planning (full-plan only) | the operator |
72
+ | `ready` | approved — an agent may start | nobody |
73
+ | `working` | claimed; ledger shows live progress | the runner |
74
+ | `for-operator` | done — evidence posted, awaiting operator review | the operator |
75
+
76
+ Modifiers coexist with state: `risky` · scope `research` / `quick-build` / `full-plan` · `epic` (map parents without a native Epic type). Boards mirror states one-way.
77
+
78
+ ## Titles, types, hierarchy
79
+
80
+ - **Title prefixes:** issues, branches and PRs use dev.md's `branch:` types plus `research:`; PR title = issue title.
81
+ - **Native issue types/fields:** Feature (feat) · Bug (fix) · Task (docs/chore/refactor/research) · Epic for parents (else label); intake sets Priority/Effort. Scope classes stay labels.
82
+ - **Hierarchy:** epic parent = map only (Destination · Decisions so far · Not clear yet · Out of scope), with native child sub-issues. Issues are work units (brief, approvals, branch, PR, evidence); tasks are checkboxes **only in the plan comment**. Blockers use dependencies; phases use milestones. Only non-epic issues get `ready`.
83
+
84
+ ## The ledger
85
+
86
+ One implementation ledger:
87
+
88
+ ```markdown
89
+ <!-- vsk:v1 type=ledger branch=<branch> -->
90
+ ## Ledger — <branch>
91
+ - <issue>-T<N>: complete (commits <base7>..<head7>[, review clean | K parked])
92
+ - <issue>-T<N>: fix round <R>/3 (<X> addressed, <Y> open — <one-liners>; commits <a>..<b>)
93
+ - Ruling: <what> — <why> — cost if wrong: <cost>
94
+ - <issue>-T<N>: parked — <finding> — Ruling: <why the code stands>
95
+ - Deferred minor: <one-liner>
96
+ ```
97
+
98
+
99
+ **Resume protocol:** brief → plan comment → ledger → `git log`; then reconcile task IDs, canonical approval history, edited authority, source/evidence, ownership and delivery effects. Preserve completed work/provenance; stale heartbeat is not stop proof. Preparation never implies issue completion. Dev-implement's ledger reference owns recovery detail.
100
+
101
+ ## `.vegastack/` workspaces
102
+
103
+ Drafts/reports: `.vegastack/.tmp/<issue-number>-<title-slug>/` (pre-issue: `intake-<slug>`), self-ignored by a `.gitignore` containing `*`. Branch checkouts: root-ignored `.vegastack/.worktrees/<issue-number>-<title-slug>/`; main stays on its default branch. Keep both outside `.git/`. Subagents save full reports and return short status. `<path-to-this-skill>` means SKILL.md’s directory.
104
+
105
+ ## Verification gate
106
+
107
+ Prove claims with fresh command output and exit codes; report failures and skips. Delegate only substantial independent parallel work, never your own verification; keep spawn counts low. Guards block machine-verifiable failures (exit 2); heuristics warn. Guards contain no AI inference; unverifiable state fails closed.
108
+
109
+ ## Review bindings
110
+
111
+ One fenced JSON each: `{"reviewBinding":{sha,baseSha,scopeDigest,verdict,findings:[{id,status}]}}` in review; `{"adjudication":{sha,reviewCommentId,operator,source:{kind,ref,quote},findings:[{id,disposition,reason}]}}` in evidence. Use full commit IDs and canonical-plan scopeDigest; status=open/resolved; disposition=accept-risk. Every open finding requires same-review operator acceptance. dev-ship’s README defines source checks. No prose exceptions.
112
+
113
+ Communicate starts/findings/direction plainly; self-contained outcomes include paths and remaining checks. Avoid invented labels/arrows; visualize usefully. Challenge ambiguity with options; never guess silently.
@@ -0,0 +1,3 @@
1
+ # Refresh contract — dev-intake
2
+
3
+ Evergreen: this skill asserts no version pins, vendor mechanism names, numeric vendor limits, or dated facts — its content is interview discipline, slicing rules, the brief template, and the approval-recording rule, all versionless. The harness question-tool mechanics it leans on are tracked by `dev-setup`'s registry (see `skills/dev-setup/refresh/`). Revisit if a future edit introduces a volatile fact.
@@ -0,0 +1,6 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "retrievalBaseline": "2026-08-27",
4
+ "note": "Evergreen waiver recorded in REFRESH.md; sources deliberately empty.",
5
+ "sources": []
6
+ }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ // dev-intake guard: deterministic checks on a drafted brief before posting.
3
+ // Missing structure blocks; quality smells only warn (heuristics never block).
4
+ // Inline quick-build plans are linted separately by dev-plan's plan-lint — the
5
+ // banned-placeholder list lives there, its single home.
6
+ //
7
+ // Exit codes: 0 pass · 1 pass-with-warnings · 2 blocked (reasons printed).
8
+ // Usage: node brief-lint.mjs --file <brief.md> --scope <research|quick-build|full-plan> --json
9
+ import { readFileSync } from 'node:fs';
10
+ import { resolve } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ const REQUIRED_HEADINGS = {
14
+ research: [/^##\s+.*question/im, /^##\s+.*answered/im],
15
+ 'quick-build': [/^##\s+Outcome\b/m, /^##\s+Tests and acceptance\b/m, /^##\s+Approach/m],
16
+ 'full-plan': [/^##\s+Outcome\b/m, /^##\s+Out of scope\b/m, /^##\s+Tests and acceptance\b/m, /^##\s+Approach/m],
17
+ };
18
+
19
+ const VAGUE_SMELLS = [
20
+ /\bworks (properly|correctly|as expected)\b/i,
21
+ /\buser[- ]friendly\b/i,
22
+ /\brobust(ly)?\b/i,
23
+ /\betc\.?\b/i,
24
+ ];
25
+
26
+ export function lintBrief(text, scope, { fix = false } = {}) {
27
+ const blocks = [];
28
+ const warns = [];
29
+
30
+ if (!REQUIRED_HEADINGS[scope]) {
31
+ return { blocks: [`unknown scope class "${scope}" (research | quick-build | full-plan)`], warns };
32
+ }
33
+ if (!/<!--\s*vsk:v1\s+type=brief\b/.test(text)) blocks.push('missing brief marker (<!-- vsk:v1 type=brief rev=n scope=... -->)');
34
+ if (scope !== 'research' && !/^\*\*Scope:\*\*/m.test(text)) {
35
+ blocks.push('missing the **Scope:** line — the announced reason must survive the conversation');
36
+ }
37
+ if (fix && !/^##\s+Reproduction\b/m.test(text)) {
38
+ blocks.push('fix-type brief without a ## Reproduction section — an unreproducible bug is research first');
39
+ }
40
+
41
+ for (const heading of REQUIRED_HEADINGS[scope]) {
42
+ if (!heading.test(text)) blocks.push(`missing required section for ${scope}: ${heading.source}`);
43
+ }
44
+
45
+ if (scope !== 'research') {
46
+ const approach = text.split(/^(?=##\s)/m).find((chunk) => /^##\s+Approach/.test(chunk));
47
+ if (approach && !/`[^`]*[/.][^`]*`/.test(approach)) {
48
+ blocks.push('Approach and touch points names no real backticked paths — grounding was skipped or unrecorded');
49
+ }
50
+ }
51
+
52
+ for (const smell of VAGUE_SMELLS) {
53
+ const hit = smell.exec(text);
54
+ if (hit) warns.push(`vague wording: "${hit[0]}" — name the observable behavior instead`);
55
+ }
56
+
57
+ return { blocks, warns };
58
+ }
59
+
60
+ const invokedDirectly = process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
61
+ if (invokedDirectly) {
62
+ const argv = process.argv.slice(2);
63
+ const json = argv.includes('--json');
64
+ const get = (flag) => { const i = argv.indexOf(flag); return i === -1 ? undefined : argv[i + 1]; };
65
+ let outcome;
66
+ const file = get('--file');
67
+ const scope = get('--scope');
68
+ if (!file || !scope) {
69
+ outcome = { blocks: ['usage: brief-lint.mjs --file <brief.md> --scope <class> [--fix] [--json]'], warns: [] };
70
+ } else {
71
+ try {
72
+ outcome = lintBrief(readFileSync(file, 'utf8'), scope, { fix: argv.includes('--fix') });
73
+ } catch (error) {
74
+ outcome = { blocks: [`cannot read brief: ${error.message}`], warns: [] };
75
+ }
76
+ }
77
+ const ok = outcome.blocks.length === 0;
78
+ const exitCode = ok ? (outcome.warns.length ? 1 : 0) : 2;
79
+ if (json) {
80
+ console.log(JSON.stringify({ guard: 'brief-lint', ok, ...outcome }, null, 2));
81
+ } else {
82
+ console.log(`brief-lint: ${ok ? (outcome.warns.length ? 'pass with warnings' : 'pass') : 'BLOCKED'}`);
83
+ for (const b of outcome.blocks) console.log(` block: ${b}`);
84
+ for (const w of outcome.warns) console.log(` warn: ${w}`);
85
+ }
86
+ process.exit(exitCode);
87
+ }