dev-loops 0.1.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 (156) hide show
  1. package/.pi/dev-loop/defaults.yaml +477 -0
  2. package/AGENTS.md +25 -0
  3. package/CHANGELOG.md +18 -0
  4. package/LICENSE +21 -0
  5. package/README.md +178 -0
  6. package/agents/dev-loop.agent.md +82 -0
  7. package/agents/developer.agent.md +37 -0
  8. package/agents/docs.agent.md +33 -0
  9. package/agents/fixer.agent.md +53 -0
  10. package/agents/quality.agent.md +28 -0
  11. package/agents/refiner.agent.md +87 -0
  12. package/agents/review.agent.md +64 -0
  13. package/cli/index.mjs +424 -0
  14. package/extension/README.md +233 -0
  15. package/extension/checks.ts +94 -0
  16. package/extension/index.ts +131 -0
  17. package/extension/post-merge-update.ts +512 -0
  18. package/extension/presentation.ts +107 -0
  19. package/lib/dev-loops-core.mjs +284 -0
  20. package/package.json +103 -0
  21. package/scripts/README.md +1007 -0
  22. package/scripts/_cli-primitives.mjs +10 -0
  23. package/scripts/_core-helpers.mjs +30 -0
  24. package/scripts/docs/validate-links.mjs +567 -0
  25. package/scripts/docs/validate-no-duplicate-rules.mjs +250 -0
  26. package/scripts/github/_review-thread-mutations.mjs +214 -0
  27. package/scripts/github/capture-review-threads.mjs +180 -0
  28. package/scripts/github/create-draft-pr.mjs +108 -0
  29. package/scripts/github/detect-checkpoint-evidence.mjs +393 -0
  30. package/scripts/github/detect-linked-issue-pr.mjs +331 -0
  31. package/scripts/github/manage-sub-issues.mjs +394 -0
  32. package/scripts/github/probe-copilot-review.mjs +323 -0
  33. package/scripts/github/ready-for-review.mjs +93 -0
  34. package/scripts/github/reconcile-draft-gate.mjs +328 -0
  35. package/scripts/github/reply-resolve-review-thread.mjs +42 -0
  36. package/scripts/github/reply-resolve-review-threads.mjs +329 -0
  37. package/scripts/github/request-copilot-review.mjs +551 -0
  38. package/scripts/github/resolve-tracker-local-spec.mjs +205 -0
  39. package/scripts/github/stage-reviewer-draft.mjs +191 -0
  40. package/scripts/github/upsert-checkpoint-verdict.mjs +694 -0
  41. package/scripts/github/verify-fresh-review-context.mjs +125 -0
  42. package/scripts/github/write-gate-findings-log.mjs +212 -0
  43. package/scripts/loop/_checkpoint-io.mjs +55 -0
  44. package/scripts/loop/_checkpoint-paths.mjs +28 -0
  45. package/scripts/loop/_handoff-contract.mjs +230 -0
  46. package/scripts/loop/_inspect-run-viewer-adapter.mjs +345 -0
  47. package/scripts/loop/_loop-evidence.mjs +32 -0
  48. package/scripts/loop/_pr-runner-coordination.mjs +611 -0
  49. package/scripts/loop/_stale-runner-detection.mjs +145 -0
  50. package/scripts/loop/_steering-state-file.mjs +134 -0
  51. package/scripts/loop/build-handoff-envelope.mjs +181 -0
  52. package/scripts/loop/checkpoint-contract.mjs +49 -0
  53. package/scripts/loop/conductor-monitor.mjs +1850 -0
  54. package/scripts/loop/conductor.mjs +214 -0
  55. package/scripts/loop/copilot-pr-handoff.mjs +493 -0
  56. package/scripts/loop/debt-remediate.mjs +304 -0
  57. package/scripts/loop/detect-change-scope.mjs +102 -0
  58. package/scripts/loop/detect-copilot-loop-state.mjs +454 -0
  59. package/scripts/loop/detect-copilot-session-activity.mjs +186 -0
  60. package/scripts/loop/detect-initial-copilot-pr-state.mjs +318 -0
  61. package/scripts/loop/detect-internal-only-pr.mjs +270 -0
  62. package/scripts/loop/detect-issue-refinement-artifact.mjs +163 -0
  63. package/scripts/loop/detect-pr-gate-coordination-state.mjs +509 -0
  64. package/scripts/loop/detect-reviewer-loop-state.mjs +231 -0
  65. package/scripts/loop/detect-stale-runner.mjs +250 -0
  66. package/scripts/loop/detect-tracker-first-loop-state.mjs +76 -0
  67. package/scripts/loop/detect-tracker-pr-state.mjs +102 -0
  68. package/scripts/loop/info.mjs +267 -0
  69. package/scripts/loop/inspect-run-viewer/cli.mjs +117 -0
  70. package/scripts/loop/inspect-run-viewer/constants.mjs +80 -0
  71. package/scripts/loop/inspect-run-viewer/graph.mjs +757 -0
  72. package/scripts/loop/inspect-run-viewer/handoff-envelope-renderer.mjs +398 -0
  73. package/scripts/loop/inspect-run-viewer/inbox.mjs +308 -0
  74. package/scripts/loop/inspect-run-viewer/managed-instance.mjs +750 -0
  75. package/scripts/loop/inspect-run-viewer/rendering.mjs +411 -0
  76. package/scripts/loop/inspect-run-viewer/server.mjs +638 -0
  77. package/scripts/loop/inspect-run-viewer/shared.mjs +103 -0
  78. package/scripts/loop/inspect-run-viewer/status.mjs +715 -0
  79. package/scripts/loop/inspect-run-viewer-ci-changes.mjs +77 -0
  80. package/scripts/loop/inspect-run-viewer.mjs +82 -0
  81. package/scripts/loop/inspect-run.mjs +382 -0
  82. package/scripts/loop/outer-loop.mjs +419 -0
  83. package/scripts/loop/pr-runner-coordination.mjs +143 -0
  84. package/scripts/loop/pre-commit-branch-guard.mjs +68 -0
  85. package/scripts/loop/pre-flight-gate.mjs +236 -0
  86. package/scripts/loop/pre-pr-ready-gate.mjs +183 -0
  87. package/scripts/loop/pre-push-main-guard.mjs +103 -0
  88. package/scripts/loop/pre-write-remote-freshness-guard.mjs +32 -0
  89. package/scripts/loop/print-gates.mjs +42 -0
  90. package/scripts/loop/resolve-dev-loop-startup.mjs +533 -0
  91. package/scripts/loop/run-conductor-cycle.mjs +322 -0
  92. package/scripts/loop/run-queue.mjs +124 -0
  93. package/scripts/loop/run-refinement-audit.mjs +513 -0
  94. package/scripts/loop/run-watch-cycle.mjs +358 -0
  95. package/scripts/loop/steer-loop.mjs +841 -0
  96. package/scripts/loop/ui-designer-review-contract.mjs +76 -0
  97. package/scripts/loop/watch-initial-copilot-pr.mjs +253 -0
  98. package/scripts/projects/add-queue-item.mjs +528 -0
  99. package/scripts/projects/ensure-queue-board.mjs +837 -0
  100. package/scripts/projects/list-queue-items.mjs +489 -0
  101. package/scripts/projects/move-queue-item.mjs +549 -0
  102. package/scripts/projects/reorder-queue-item.mjs +518 -0
  103. package/scripts/refine/_refine-helpers.mjs +258 -0
  104. package/scripts/refine/prose-linkage-detector.mjs +92 -0
  105. package/scripts/refine/refinement-completeness-checker.mjs +88 -0
  106. package/scripts/refine/scope-boundary-cross-checker.mjs +163 -0
  107. package/scripts/refine/tree-integrity-validator.mjs +211 -0
  108. package/scripts/refine/verify.mjs +178 -0
  109. package/scripts/repo-wiki-local.mjs +156 -0
  110. package/scripts/repo-wiki.mjs +119 -0
  111. package/skills/copilot-pr-followup/SKILL.md +380 -0
  112. package/skills/dev-loop/SKILL.md +141 -0
  113. package/skills/dev-loop/scripts/dev-mode-context.mjs +152 -0
  114. package/skills/dev-loop/scripts/dev-mode-context.test.mjs +80 -0
  115. package/skills/dev-loop/scripts/init-phase.mjs +71 -0
  116. package/skills/dev-loop/scripts/log-bash-exit-1.mjs +25 -0
  117. package/skills/dev-loop/scripts/phase-files.mjs +29 -0
  118. package/skills/dev-loop/scripts/post-gate-verdict-fallback.mjs +480 -0
  119. package/skills/dev-loop/scripts/post-gate-verdict-fallback.test.mjs +732 -0
  120. package/skills/dev-loop/scripts/render-template.mjs +82 -0
  121. package/skills/dev-loop/scripts/render-template.test.mjs +63 -0
  122. package/skills/dev-loop/templates/bootstrap-agents.md +26 -0
  123. package/skills/dev-loop/templates/bootstrap-implementation-state.md +31 -0
  124. package/skills/dev-loop/templates/bootstrap-implementation-workflow.md +17 -0
  125. package/skills/dev-loop/templates/dev-mode-retrospective.md +15 -0
  126. package/skills/dev-loop/templates/dev-mode-review.md +17 -0
  127. package/skills/dev-loop/templates/dev-mode-skill-changes.md +11 -0
  128. package/skills/dev-loop/templates/merged-phase-plan.md +19 -0
  129. package/skills/dev-loop/templates/phase-doc.md +27 -0
  130. package/skills/dev-loop/templates/phase-summary.md +13 -0
  131. package/skills/dev-loop/templates/phase-variant.md +15 -0
  132. package/skills/dev-loop/templates/retrospective.md +11 -0
  133. package/skills/dev-loop/templates/review.md +32 -0
  134. package/skills/dev-loop/templates/ui-vision-review.md +55 -0
  135. package/skills/docs/acceptance-criteria-verification.md +21 -0
  136. package/skills/docs/anti-patterns.md +21 -0
  137. package/skills/docs/artifact-authority-contract.md +119 -0
  138. package/skills/docs/confirmation-rules.md +28 -0
  139. package/skills/docs/copilot-ci-status-contract.md +52 -0
  140. package/skills/docs/copilot-loop-operations.md +233 -0
  141. package/skills/docs/debt-remediation-contract.md +107 -0
  142. package/skills/docs/entrypoint-strategies.md +115 -0
  143. package/skills/docs/epic-tree-refinement-procedure.md +234 -0
  144. package/skills/docs/issue-intake-procedure.md +235 -0
  145. package/skills/docs/main-agent-contract.md +72 -0
  146. package/skills/docs/merge-preconditions.md +29 -0
  147. package/skills/docs/pr-lifecycle-contract.md +209 -0
  148. package/skills/docs/public-dev-loop-contract.md +497 -0
  149. package/skills/docs/retrospective-checkpoint-contract.md +159 -0
  150. package/skills/docs/stop-conditions.md +29 -0
  151. package/skills/docs/structural-quality.md +42 -0
  152. package/skills/docs/tracker-first-loop-state.md +281 -0
  153. package/skills/docs/validation-policy.md +27 -0
  154. package/skills/docs/workflow-handoff-contract.md +135 -0
  155. package/skills/final-approval/SKILL.md +19 -0
  156. package/skills/local-implementation/SKILL.md +640 -0
@@ -0,0 +1,82 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ export function renderTemplate(template, variables) {
6
+ if (typeof template !== "string") {
7
+ throw new Error("template must be a string");
8
+ }
9
+
10
+ return template.replace(/{{\s*([a-zA-Z0-9_-]+)\s*}}/g, (match, key) => {
11
+ if (!(key in variables)) {
12
+ throw new Error(`Missing template variable: ${key}`);
13
+ }
14
+
15
+ return String(variables[key]);
16
+ });
17
+ }
18
+
19
+ export async function materializeTemplate(templatePath, outputPath, variables) {
20
+ const template = await readFile(templatePath, "utf8");
21
+ const content = renderTemplate(template, variables);
22
+ await mkdir(path.dirname(outputPath), { recursive: true });
23
+ await writeFile(outputPath, content, "utf8");
24
+ return { templatePath, outputPath, content };
25
+ }
26
+
27
+ export function parseCliArgs(argv) {
28
+ const args = [...argv];
29
+ let templatePath;
30
+ let outputPath;
31
+ let variables = {};
32
+
33
+ while (args.length > 0) {
34
+ const token = args.shift();
35
+
36
+ if (token === "--template") {
37
+ templatePath = args.shift();
38
+ continue;
39
+ }
40
+
41
+ if (token === "--output") {
42
+ outputPath = args.shift();
43
+ continue;
44
+ }
45
+
46
+ if (token === "--vars") {
47
+ variables = JSON.parse(args.shift() ?? "{}");
48
+ continue;
49
+ }
50
+
51
+ throw new Error(`Unknown argument: ${token}`);
52
+ }
53
+
54
+ if (!templatePath) {
55
+ throw new Error("Missing required --template <path> argument");
56
+ }
57
+
58
+ if (!outputPath) {
59
+ throw new Error("Missing required --output <path> argument");
60
+ }
61
+
62
+ return { templatePath, outputPath, variables };
63
+ }
64
+
65
+ export async function runCli(argv = process.argv.slice(2)) {
66
+ const options = parseCliArgs(argv);
67
+ const result = await materializeTemplate(options.templatePath, options.outputPath, options.variables);
68
+ process.stdout.write(
69
+ `${JSON.stringify({ ok: true, templatePath: result.templatePath, outputPath: result.outputPath })}\n`,
70
+ );
71
+ }
72
+
73
+ const invokedAsScript = process.argv[1]
74
+ ? import.meta.url === pathToFileURL(process.argv[1]).href
75
+ : false;
76
+
77
+ if (invokedAsScript) {
78
+ runCli().catch((error) => {
79
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
80
+ process.exitCode = 1;
81
+ });
82
+ }
@@ -0,0 +1,63 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ import { materializeTemplate, parseCliArgs, renderTemplate } from "./render-template.mjs";
8
+
9
+ test("render-template renders placeholders deterministically", () => {
10
+ assert.equal(
11
+ renderTemplate("# Phase {{phase}} variant {{variant}}\n", {
12
+ phase: "phase-0",
13
+ variant: "a",
14
+ }),
15
+ "# Phase phase-0 variant a\n",
16
+ );
17
+ });
18
+
19
+ test("render-template throws on missing variables", () => {
20
+ assert.throws(() => renderTemplate("Hello {{name}}", {}), /missing template variable: name/i);
21
+ });
22
+
23
+ test("render-template materializes a template file", async () => {
24
+ const tempDir = await mkdtemp(path.join(os.tmpdir(), "dev-loop-render-template-"));
25
+ const templatePath = path.join(tempDir, "template.md");
26
+ const outputPath = path.join(tempDir, "out", "variant-a.md");
27
+
28
+ try {
29
+ await writeFile(templatePath, "# {{phase}}\n{{body}}\n", "utf8");
30
+ await materializeTemplate(templatePath, outputPath, {
31
+ phase: "phase-0",
32
+ body: "hello",
33
+ });
34
+
35
+ const output = await readFile(outputPath, "utf8");
36
+ assert.equal(output, "# phase-0\nhello\n");
37
+ } finally {
38
+ await rm(tempDir, { recursive: true, force: true });
39
+ }
40
+ });
41
+
42
+ test("render-template parses cli args", () => {
43
+ assert.deepEqual(
44
+ parseCliArgs([
45
+ "--template",
46
+ "templates/x.md",
47
+ "--output",
48
+ "tmp/x.md",
49
+ "--vars",
50
+ '{"phase":"phase-0"}',
51
+ ]),
52
+ {
53
+ templatePath: "templates/x.md",
54
+ outputPath: "tmp/x.md",
55
+ variables: { phase: "phase-0" },
56
+ },
57
+ );
58
+ });
59
+
60
+ test("render-template requires template and output args", () => {
61
+ assert.throws(() => parseCliArgs(["--output", "tmp/x.md"]), /missing required --template/i);
62
+ assert.throws(() => parseCliArgs(["--template", "templates/x.md"]), /missing required --output/i);
63
+ });
@@ -0,0 +1,26 @@
1
+ # AGENTS.md
2
+
3
+ ## Project contract
4
+
5
+ This repository uses the `dev-loop` skill as the primary implementation workflow.
6
+
7
+ The skill may be provided repo-locally or globally; this contract does not assume a local skill path.
8
+
9
+ ## Working agreement
10
+
11
+ - Work test-first for all non-trivial logic.
12
+ - Maintain at least 90% coverage for lines, statements, functions, and branches.
13
+ - Implement one phase at a time.
14
+ - Use fan-out / fan-in / review / merge before implementing each phase.
15
+ - Keep logs under `tmp/` in deterministic phase-scoped paths.
16
+ - Use local branches and small commits only after local verification.
17
+ - Do not assume GitHub PR or issue workflows.
18
+
19
+ ## Core guard rails
20
+
21
+ - KISS
22
+ - SRP
23
+ - YAGNI
24
+ - strict TypeScript
25
+ - thin runtime glue
26
+ - no production reliance on Pi private internals
@@ -0,0 +1,31 @@
1
+ # Implementation state
2
+
3
+ ## Status
4
+
5
+ Preparation is in place. Implementation has not started.
6
+
7
+ ## Current source of truth
8
+
9
+ - Product plan: [Project Plan](../../../PLAN.md)
10
+ - Durable phase plans: [Phase Plan](../../../docs/phases/)
11
+ - Execution skill: `dev-loop`
12
+ - Repo contract: [Agent Instructions](../../../AGENTS.md)
13
+ - Workflow explainer: [Implementation Workflow](../../../docs/IMPLEMENTATION_WORKFLOW.md)
14
+ - tmp index for fresh-context inspection if present locally: `tmp/phases/index.json`
15
+
16
+ ## Next action for a fresh session
17
+
18
+ If the user says **"start implementation"**:
19
+
20
+ 1. read [Project Plan](../../../PLAN.md)
21
+ 2. load the `dev-loop` skill
22
+ 3. read [Agent Instructions](../../../AGENTS.md) if it exists
23
+ 4. read [Implementation Workflow](../../../docs/IMPLEMENTATION_WORKFLOW.md)
24
+ 5. read the current durable phase plan under `docs/phases/` if it exists
25
+ 6. inspect `tmp/phases/` only if it exists locally and is relevant
26
+ 7. read this file
27
+ 8. start with the next unfinished phase only
28
+
29
+ ## Next unfinished phase
30
+
31
+ Phase 0 — define the workflow convention, durable phase-plan format, and initial package boundary.
@@ -0,0 +1,17 @@
1
+ # Implementation workflow
2
+
3
+ This file is optional. The primary execution entrypoint is the `dev-loop` skill.
4
+
5
+ Use this file for repo-specific workflow notes that complement the skill.
6
+
7
+ ## Defaults
8
+
9
+ - one phase at a time
10
+ - [Project Plan](../../../PLAN.md) holds roadmap/product truth
11
+ - `docs/phases/phase-<n>.md` holds the durable plan for the active phase
12
+ - `tmp/phases/phase-<n>/` holds temporary local execution artifacts, reviews, and logs
13
+ - fan-out / fan-in / review / merge before coding
14
+ - test-first
15
+ - deterministic tmp logging
16
+ - local validation before phase completion
17
+ - local branches and small commits only after verification
@@ -0,0 +1,15 @@
1
+ # Phase {{phase}} dev-mode retrospective
2
+
3
+ ## Iteration reviewed
4
+
5
+ ## What the loop did well
6
+
7
+ ## What created friction or waste
8
+
9
+ ## Prompt follow-ups required
10
+
11
+ ## Prompt and workflow changes applied
12
+
13
+ ## Validation of the follow-up changes
14
+
15
+ ## Next dev-mode watchpoints
@@ -0,0 +1,17 @@
1
+ # Phase {{phase}} dev-mode review
2
+
3
+ Optional analytical notes that support the required [Dev Mode Retrospective](./dev-mode-retrospective.md).
4
+
5
+ ## Iteration reviewed
6
+
7
+ ## Artifact inputs reviewed
8
+
9
+ ## What the skill did well
10
+
11
+ ## Friction and failure patterns
12
+
13
+ ## Deterministic tooling gaps
14
+
15
+ ## Recommended skill or workflow changes
16
+
17
+ ## Decision
@@ -0,0 +1,11 @@
1
+ # Phase {{phase}} dev-mode skill changes
2
+
3
+ ## Trigger
4
+
5
+ ## Changes made
6
+
7
+ ## Why these changes were chosen
8
+
9
+ ## Validation
10
+
11
+ ## Remaining gaps
@@ -0,0 +1,19 @@
1
+ # Phase {{phase}} merged plan
2
+
3
+ ## Selected direction
4
+
5
+ ## Exact scope
6
+
7
+ ## Explicit non-goals
8
+
9
+ ## Tests to write first
10
+
11
+ ## Implementation order
12
+
13
+ ## Validation steps
14
+
15
+ ## Acceptance criteria
16
+
17
+ ## Definition of done
18
+
19
+ ## Risks / watchpoints
@@ -0,0 +1,27 @@
1
+ # {{phase}} durable plan
2
+
3
+ ## Status
4
+
5
+ Planning
6
+
7
+ ## Objective
8
+
9
+ ## Why this phase exists now
10
+
11
+ ## In scope
12
+
13
+ ## Explicit non-goals
14
+
15
+ ## Acceptance criteria
16
+
17
+ ## Definition of done
18
+
19
+ ## Validation approach
20
+
21
+ ## Durable decisions
22
+
23
+ ## Open questions
24
+
25
+ ## Links to execution artifacts
26
+
27
+ - local execution artifacts may exist under `tmp/phases/{{phase}}/`
@@ -0,0 +1,13 @@
1
+ # Phase {{phase}} summary
2
+
3
+ ## What was planned
4
+
5
+ ## What was implemented
6
+
7
+ ## Tests added or updated
8
+
9
+ ## Validation results
10
+
11
+ ## Decisions recorded
12
+
13
+ ## Follow-ups for next phase
@@ -0,0 +1,15 @@
1
+ # Phase {{phase}} variant {{variant}}
2
+
3
+ ## Intent
4
+
5
+ ## Phase scope
6
+
7
+ ## Files/modules touched
8
+
9
+ ## Tests to add first
10
+
11
+ ## Implementation order
12
+
13
+ ## Acceptance criteria
14
+
15
+ ## Risks / non-goals
@@ -0,0 +1,11 @@
1
+ # Phase {{phase}} retrospective
2
+
3
+ ## What worked well
4
+
5
+ ## What caused friction or waste
6
+
7
+ ## Fan-out / fan-in / review loop effectiveness
8
+
9
+ ## What to change in the skill or workflow next time
10
+
11
+ ## What a fresh session should know before the next phase
@@ -0,0 +1,32 @@
1
+ # Phase {{phase}} merged-plan review
2
+
3
+ ## Review verdict
4
+
5
+ ## Scope overreach check
6
+
7
+ ## Default pre-approval gate
8
+ <!-- Resolve angles from config: resolveGateAngles(config, "preApproval") -->
9
+ - configured angle checks: add one bullet per configured pre-approval angle (for example `dry`, `kiss`, `yagni`, `srp`, `soc` when defaults apply)
10
+ - fallback note: if parallel execution of the configured review angles is impractical, record why and confirm all configured angles were still covered
11
+
12
+ ## Additional design-principle check (SRP, etc.)
13
+
14
+ ## Test and validation check
15
+
16
+ ## Module boundary check
17
+
18
+ ## Pi API / runtime coupling check
19
+
20
+ ## Acceptance criteria clarity check
21
+
22
+ ## Definition-of-done clarity check
23
+
24
+ ## Review-surface completeness check
25
+ - review-surface completeness: confirm the merged plan and durable phase doc both carry stable definition-of-done output
26
+ - confirm the review surface checks the planned definition of done instead of only acceptance criteria
27
+
28
+ ## RFC-escalation sanity check
29
+ - confirm RFC-worthy technical decisions are escalated to the parent session / human operator
30
+ - confirm the parent-session receiving boundary and decision ownership remain explicit
31
+
32
+ ## Required revisions
@@ -0,0 +1,55 @@
1
+ # Vision-model UI review prompt template
2
+
3
+ Use this template when `uiReviewMode` is `vision`.
4
+
5
+ You are a vision-capable UI reviewer (model: `gpt-5.4`) reviewing deterministic named-state artifacts produced by `captureNamedUiState()`.
6
+
7
+ ## Inputs
8
+
9
+ - `acceptanceCriteria`: required list of UI acceptance criteria
10
+ - `reviewBrief`: required short focus brief
11
+ - `artifactBundle.sliceId`: required UI slice id
12
+ - `artifactBundle.namedStates[]`: required list of named states
13
+ - `stateName`
14
+ - `screenshotPath` (must point to `screenshot.png`)
15
+ - `statePath` (must point to `state.json`)
16
+
17
+ ## Review policy
18
+
19
+ 1. Fail closed when required inputs are missing, ambiguous, or unreadable.
20
+ 2. Ground every finding in one or more `screenshotPath` and `statePath` references.
21
+ 3. Evaluate layout, hierarchy, spacing, clipping, overlap, contrast, callouts/highlighting, and state-transition clarity against the acceptance criteria and review brief.
22
+ 4. Return only deterministic findings; do not invent evidence that is not visible in artifacts.
23
+
24
+ ## Required output format
25
+
26
+ Allowed enum values:
27
+ - `outcome`: `"continue_ui_fix_loop"` | `"ui_review_satisfied"` | `"blocked_needs_human_decision"`
28
+ - `severity`: `"high"` | `"medium"` | `"low"`
29
+
30
+ `blockedReason` must always be present in the output. Set it to `null` unless `outcome` is `"blocked_needs_human_decision"`, in which case provide a non-empty string explaining the block reason.
31
+
32
+ Return strict JSON with this shape (example uses concrete values):
33
+
34
+ ```json
35
+ {
36
+ "outcome": "ui_review_satisfied",
37
+ "summary": "short overall verdict",
38
+ "findings": [
39
+ {
40
+ "severity": "medium",
41
+ "stateName": "named state label",
42
+ "evidence": {
43
+ "screenshotPath": "test-results/ui-smoke/<sliceId>/named-states/<state-slug>/screenshot.png",
44
+ "statePath": "test-results/ui-smoke/<sliceId>/named-states/<state-slug>/state.json"
45
+ },
46
+ "problem": "what is visually wrong or unclear",
47
+ "suggestedFix": "specific corrective action"
48
+ }
49
+ ],
50
+ "nextIterationFocus": [
51
+ "small, actionable UI fix target"
52
+ ],
53
+ "blockedReason": null
54
+ }
55
+ ```
@@ -0,0 +1,21 @@
1
+ # Acceptance Criteria Verification
2
+
3
+ Extracted procedure for verifying issue acceptance criteria during the `pre_approval_gate`. Referenced from [Copilot PR Follow-up Skill](../copilot-pr-followup/SKILL.md#pre-approval-gate-contract).
4
+
5
+ ## Procedure
6
+
7
+ Before posting the `pre_approval_gate` comment, verify every acceptance criteria checklist item in the issue linked to this PR:
8
+
9
+ 1. **Resolve the linked issue number deterministically:** use `gh pr view <pr-number> --repo <owner/name> --json closingIssuesReferences,body` and apply this decision tree: if there is exactly one closing issue reference, use it; else if there is exactly one PR-body `Closes #N` / `Fixes #N` pattern, use it; otherwise (zero or multiple candidates), post the gate comment with verdict `blocked` (gate cannot complete deterministically) rather than guessing.
10
+
11
+ 2. **Read the issue body:** `gh issue view <issue-number> --repo <owner/name> --json body`
12
+
13
+ 3. **Extract checklist items** from the **Acceptance criteria** section of the issue body (both `- [ ]` unchecked and `- [x]` already-checked items). Ignore checklist items from other sections (DoD, tasks, non-goals) that are not acceptance criteria.
14
+
15
+ 4. **Verify each AC item** against the proposed changes on the current PR head.
16
+
17
+ 5. **Update the issue body once:** compute the fully-updated issue body by replacing each verified item's `- [ ]` with `- [x]`, write it to a temporary file, and perform a single `gh issue edit <issue-number> --body-file <tmp-file> --repo <owner/name>`. Do not issue one edit per item; prefer `--body-file` over inline `--body` to avoid shell quoting/escaping hazards.
18
+
19
+ 6. **Post the gate comment:** always post a `pre_approval_gate` comment (the checkpoint verdict comment contract requires a visible comment even for non-`clean` verdicts). Use verdict `clean` only when all AC items are verified; use verdict `findings_present` when any AC item is not satisfied and requires follow-up fixes; use verdict `blocked` when the gate cannot complete deterministically (for example no linked issue, ambiguous issue linkage, or the issue body is unavailable). In all cases include a note on AC verification status.
20
+
21
+ When the issue body has no AC checklist items, post the gate comment with verdict `findings_present` and note that fact explicitly rather than assuming satisfaction.
@@ -0,0 +1,21 @@
1
+ # Anti-patterns
2
+
3
+ Canonical owner for anti-pattern guidance across all workflow families.
4
+
5
+ ## Core anti-patterns
6
+
7
+ 1. **Skipping fan-out/fan-in for non-trivial changes**: Do not implement directly without refinement when scope exceeds light-mode thresholds.
8
+ 2. **Routing review-only work through local_implementation**: Review-only comparison, synthesis, or consolidation must use `refiner` agent, not `dev-loop` + `local_implementation`.
9
+ 3. **Thin placeholder PR descriptions**: Always include change summary, scope/context, acceptance criteria, definition of done, non-goals, and `Closes #N`.
10
+ 4. **Merging directly to main without PR**: Use PR-based remote loop when practical.
11
+ 5. **Duplicate worktree paths**: Check `git worktree list` before creating new worktrees; reuse existing matching worktrees.
12
+ 6. **Main-checkout mutation**: Reserve main checkout for inspection/control; use `tmp/worktrees/` paths for mutation work.
13
+
14
+ ## Light mode exception
15
+
16
+ Small scoped changes (≤3 files, ≤200 lines) may skip fan-out/fan-in but must still run validation and a single review pass. See [Local Implementation](../local-implementation/SKILL.md) for details.
17
+
18
+ ## Cross-references
19
+
20
+ - [Structural quality](structural-quality.md)
21
+ - [Validation policy](validation-policy.md)
@@ -0,0 +1,119 @@
1
+ # Artifact authority contract
2
+
3
+ This document is the canonical authority for the artifact-selection model: when work originates from a GitHub issue (tracker-first) vs a persisted markdown plan file (local-planning).
4
+
5
+ This canonical owner lives in the shipped `skills/docs/` surface because installed skill/runtime consumers reliably own the skills subtree. In installed layouts, read the same contract via [Artifact Authority Contract](../docs/artifact-authority-contract.md) from the installed skill directory.
6
+
7
+ Other repo docs may summarize or link this contract, but they should not redefine it.
8
+
9
+ ## Two-tier model
10
+
11
+ dev-loops supports two mutually exclusive artifact authority modes. Every work item must originate from exactly one authoritative artifact — a GitHub issue or a persisted markdown plan file. No work may originate from a PR or direct local change unless explicitly requested.
12
+
13
+ ### Tracker-first (default)
14
+
15
+ **GitHub issues are the authoritative artifact store.** Work originates from a GitHub issue. A linked PR is the execution artifact. GitHub is the canonical source of truth for issue identity, acceptance criteria, scope, and lifecycle state.
16
+
17
+ Artifacts:
18
+ - **Planning artifact:** GitHub issue (title, body, labels, assignees, acceptance criteria)
19
+ - **Execution artifact:** GitHub PR (linked to issue; created during implementation)
20
+ - **No local duplicate:** Do not create `docs/phases/phase-<n>.md` for the same session when a GitHub issue is the canonical spec
21
+
22
+ Key contract:
23
+ - GitHub issue state is authoritative — not local notes or chat context
24
+ - A linked PR is the single canonical follow-up artifact for the issue
25
+ - When an open linked PR exists, reuse it rather than opening another
26
+ - Implementation may proceed through either the GitHub-first routed path or the local implementation strategy (see [Public Dev Loop Contract](public-dev-loop-contract.md) `targetPreference`)
27
+
28
+ ### Local-planning (opt-out)
29
+
30
+ **Persisted markdown plan files are the authoritative artifact store.** Work originates from a markdown plan file committed to the repository. No GitHub issue is required. GitHub PRs are still used for review and merge, but the plan file is the canonical spec.
31
+
32
+ Artifacts:
33
+ - **Planning artifact:** Persisted markdown plan file (e.g., `docs/phases/phase-<n>.md`)
34
+ - **Execution artifact:** Local branch and associated GitHub PR (created during implementation)
35
+ - **No GitHub issue:** The plan file replaces the issue as the canonical spec
36
+
37
+ Key contract:
38
+ - The markdown plan file is the canonical spec — not a duplicate of a tracker issue
39
+ - GitHub issues may still be used for tracking or linking, but the plan file is authoritative for scope and acceptance criteria
40
+ - A tracker-backed local implementation session (GitHub issue as canonical spec) must not also maintain a duplicate `docs/phases/phase-<n>.md` — see [Public Dev Loop Contract](public-dev-loop-contract.md) "Tracker-backed local implementation input-source contract"
41
+
42
+ ### Mode selection table
43
+
44
+ | Mode | Canonical artifact | GitHub issue required | Settings values |
45
+ |---|---|---|---|
46
+ | Tracker-first (default) | GitHub issue | Yes | `strategy.default: github-first` |
47
+ | Local-planning (opt-out) | Markdown plan file | No | `strategy.default: local-first` |
48
+
49
+ `inputSource.default` further disambiguates local-first startup:
50
+ | inputSource | Meaning |
51
+ |---|---|
52
+ | `tracker` (default) | Local agent implements from the GitHub issue body; no phase doc created |
53
+ | `phase-docs` | Local agent implements from persisted phase docs (e.g., `docs/phases/phase-<n>.md`) |
54
+
55
+ ## Settings mechanism
56
+
57
+ Artifact authority mode is controlled by `.devloops` at repo root:
58
+
59
+ ```yaml
60
+ # .devloops
61
+ strategy:
62
+ default: github-first # tracker-first (GitHub issue required)
63
+ # default: local-first # local-planning (markdown plan file)
64
+ inputSource:
65
+ default: tracker # spec source for local-first: tracker (issue body) or phase-docs
66
+ ```
67
+
68
+ The `strategy.default` key serves dual purpose:
69
+ 1. It selects the artifact authority mode (tracker-first vs local-planning)
70
+ 2. It sets the default routing preference for `targetPreference` in dev-loop startup
71
+
72
+ The `inputSource.default` key disambiguates local-first startup:
73
+ - `tracker` (default): local agent implements from the GitHub issue body; the issue is canonical spec
74
+ - `phase-docs`: local agent implements from persisted phase docs; no tracker issue required
75
+
76
+ These keys are already defined in `.pi/dev-loop/defaults.yaml` (shipped with dev-loops) and may be overridden in `.devloops` (per-repo).
77
+
78
+ ### Defaults resolution
79
+
80
+ 1. `.pi/dev-loop/defaults.yaml` — shipped default (`github-first`)
81
+ 2. `.devloops` — per-repo override (takes precedence)
82
+
83
+ ### Explicit non-knobs
84
+
85
+ These are not valid artifact authority mode selectors:
86
+ - `strategy.default: copilot` — not a valid mode; must be `github-first` or `local-first`
87
+ - Free-form string values — fail closed
88
+ - Omitting `strategy.default` entirely — defaults to `github-first` from the shipped defaults
89
+
90
+ ## dev-loops own mode
91
+
92
+ dev-loops is **tracker-first (opted in, GitHub backend).**
93
+
94
+ - **Mode:** Tracker-first
95
+ - **Settings:** `.pi/dev-loop/defaults.yaml` sets `strategy.default: github-first`
96
+ - **Artifact authority:** GitHub issues are the canonical spec for all work in this repository
97
+ - **No local-planning override:** This repo does not opt out to local-planning mode
98
+ - **Why tracker-first:** All work in this repo originates from GitHub issues. The public dev-loop contract, Copilot follow-up state machines, and gate pipeline all assume issues are the primary artifact. Self-improvement work on dev-loops itself follows the same tracker-first contract.
99
+
100
+ ## Relationship to other docs
101
+
102
+ | Doc | Relationship |
103
+ |---|---|
104
+ | [Public Dev Loop Contract](public-dev-loop-contract.md) | This contract is the canonical entrypoint; artifact authority contract defines the artifact model it assumes |
105
+ | [Tracker-First Loop State](tracker-first-loop-state.md) | That doc defines the PR-level state machine for tracker-first PR workflows — it is about execution state, not artifact authority |
106
+ | [Main Agent Contract](main-agent-contract.md) | Defines the delegation boundary; artifact authority defines which artifacts govern work |
107
+ | AGENTS.md | Repo constitution; cites the work-origin rule and points to this contract |
108
+ | [Dev Loop Skill](../dev-loop/SKILL.md) | Public entrypoint skill; cites the work-origin rule and points to this contract |
109
+
110
+ ### Distinction: artifact authority vs tracker-first PR workflow
111
+
112
+ `tracker-first-loop-state.md` defines a state machine for PR lifecycle management when a tracker item (e.g., Shortcut story) drives a GitHub PR. That is a **PR-level workflow contract**, not the artifact authority model. The term "tracker-first" in that doc refers to tracker-driven PR state transitions — it does not redefine the artifact authority contract defined here.
113
+
114
+ ## Non-goals
115
+
116
+ - Defining tracker adapters or multi-tracker support
117
+ - Specifying how PRs map to issues in detail (that is the [Public Dev Loop Contract](public-dev-loop-contract.md))
118
+ - Changing the dev-loop startup resolver behavior
119
+ - Adding tracker-specific settings beyond `inputSource` — further tracker adapters or multi-tracker support remain out of scope
@@ -0,0 +1,28 @@
1
+ # Confirmation rules
2
+
3
+ Canonical owner for agent confirmation / authorization rules across all workflow families.
4
+
5
+ ## Core rule
6
+
7
+ Before any state-changing action, get explicit confirmation unless the latest user message already clearly authorizes that exact action.
8
+
9
+ ## What counts as confirmation
10
+
11
+ - ✅ Explicit authorization in the current conversation
12
+ - ✅ Pre-authorized merge or mutation scope (e.g. "Merge authorized if gates green")
13
+ - ❌ Questions, preferences, future-tense statements
14
+ - ❌ Implied approval from prior turns
15
+ - ❌ Bare response `ok`
16
+
17
+ ## Where this rule applies
18
+
19
+ - All routed strategies (`local_implementation`, `copilot_pr_followup`, `issue_intake`, `reviewer_fixer`, `final_approval`)
20
+ - All gate entries (`draft_gate`, `pre_approval_gate`)
21
+ - All merge operations
22
+ - All force-push / history-rewriting operations
23
+
24
+ ## Cross-references
25
+
26
+ - [Stop conditions](stop-conditions.md)
27
+ - [Merge preconditions](merge-preconditions.md)
28
+ - [Public Dev Loop Contract](public-dev-loop-contract.md)