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.
- package/.pi/dev-loop/defaults.yaml +477 -0
- package/AGENTS.md +25 -0
- package/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/agents/dev-loop.agent.md +82 -0
- package/agents/developer.agent.md +37 -0
- package/agents/docs.agent.md +33 -0
- package/agents/fixer.agent.md +53 -0
- package/agents/quality.agent.md +28 -0
- package/agents/refiner.agent.md +87 -0
- package/agents/review.agent.md +64 -0
- package/cli/index.mjs +424 -0
- package/extension/README.md +233 -0
- package/extension/checks.ts +94 -0
- package/extension/index.ts +131 -0
- package/extension/post-merge-update.ts +512 -0
- package/extension/presentation.ts +107 -0
- package/lib/dev-loops-core.mjs +284 -0
- package/package.json +103 -0
- package/scripts/README.md +1007 -0
- package/scripts/_cli-primitives.mjs +10 -0
- package/scripts/_core-helpers.mjs +30 -0
- package/scripts/docs/validate-links.mjs +567 -0
- package/scripts/docs/validate-no-duplicate-rules.mjs +250 -0
- package/scripts/github/_review-thread-mutations.mjs +214 -0
- package/scripts/github/capture-review-threads.mjs +180 -0
- package/scripts/github/create-draft-pr.mjs +108 -0
- package/scripts/github/detect-checkpoint-evidence.mjs +393 -0
- package/scripts/github/detect-linked-issue-pr.mjs +331 -0
- package/scripts/github/manage-sub-issues.mjs +394 -0
- package/scripts/github/probe-copilot-review.mjs +323 -0
- package/scripts/github/ready-for-review.mjs +93 -0
- package/scripts/github/reconcile-draft-gate.mjs +328 -0
- package/scripts/github/reply-resolve-review-thread.mjs +42 -0
- package/scripts/github/reply-resolve-review-threads.mjs +329 -0
- package/scripts/github/request-copilot-review.mjs +551 -0
- package/scripts/github/resolve-tracker-local-spec.mjs +205 -0
- package/scripts/github/stage-reviewer-draft.mjs +191 -0
- package/scripts/github/upsert-checkpoint-verdict.mjs +694 -0
- package/scripts/github/verify-fresh-review-context.mjs +125 -0
- package/scripts/github/write-gate-findings-log.mjs +212 -0
- package/scripts/loop/_checkpoint-io.mjs +55 -0
- package/scripts/loop/_checkpoint-paths.mjs +28 -0
- package/scripts/loop/_handoff-contract.mjs +230 -0
- package/scripts/loop/_inspect-run-viewer-adapter.mjs +345 -0
- package/scripts/loop/_loop-evidence.mjs +32 -0
- package/scripts/loop/_pr-runner-coordination.mjs +611 -0
- package/scripts/loop/_stale-runner-detection.mjs +145 -0
- package/scripts/loop/_steering-state-file.mjs +134 -0
- package/scripts/loop/build-handoff-envelope.mjs +181 -0
- package/scripts/loop/checkpoint-contract.mjs +49 -0
- package/scripts/loop/conductor-monitor.mjs +1850 -0
- package/scripts/loop/conductor.mjs +214 -0
- package/scripts/loop/copilot-pr-handoff.mjs +493 -0
- package/scripts/loop/debt-remediate.mjs +304 -0
- package/scripts/loop/detect-change-scope.mjs +102 -0
- package/scripts/loop/detect-copilot-loop-state.mjs +454 -0
- package/scripts/loop/detect-copilot-session-activity.mjs +186 -0
- package/scripts/loop/detect-initial-copilot-pr-state.mjs +318 -0
- package/scripts/loop/detect-internal-only-pr.mjs +270 -0
- package/scripts/loop/detect-issue-refinement-artifact.mjs +163 -0
- package/scripts/loop/detect-pr-gate-coordination-state.mjs +509 -0
- package/scripts/loop/detect-reviewer-loop-state.mjs +231 -0
- package/scripts/loop/detect-stale-runner.mjs +250 -0
- package/scripts/loop/detect-tracker-first-loop-state.mjs +76 -0
- package/scripts/loop/detect-tracker-pr-state.mjs +102 -0
- package/scripts/loop/info.mjs +267 -0
- package/scripts/loop/inspect-run-viewer/cli.mjs +117 -0
- package/scripts/loop/inspect-run-viewer/constants.mjs +80 -0
- package/scripts/loop/inspect-run-viewer/graph.mjs +757 -0
- package/scripts/loop/inspect-run-viewer/handoff-envelope-renderer.mjs +398 -0
- package/scripts/loop/inspect-run-viewer/inbox.mjs +308 -0
- package/scripts/loop/inspect-run-viewer/managed-instance.mjs +750 -0
- package/scripts/loop/inspect-run-viewer/rendering.mjs +411 -0
- package/scripts/loop/inspect-run-viewer/server.mjs +638 -0
- package/scripts/loop/inspect-run-viewer/shared.mjs +103 -0
- package/scripts/loop/inspect-run-viewer/status.mjs +715 -0
- package/scripts/loop/inspect-run-viewer-ci-changes.mjs +77 -0
- package/scripts/loop/inspect-run-viewer.mjs +82 -0
- package/scripts/loop/inspect-run.mjs +382 -0
- package/scripts/loop/outer-loop.mjs +419 -0
- package/scripts/loop/pr-runner-coordination.mjs +143 -0
- package/scripts/loop/pre-commit-branch-guard.mjs +68 -0
- package/scripts/loop/pre-flight-gate.mjs +236 -0
- package/scripts/loop/pre-pr-ready-gate.mjs +183 -0
- package/scripts/loop/pre-push-main-guard.mjs +103 -0
- package/scripts/loop/pre-write-remote-freshness-guard.mjs +32 -0
- package/scripts/loop/print-gates.mjs +42 -0
- package/scripts/loop/resolve-dev-loop-startup.mjs +533 -0
- package/scripts/loop/run-conductor-cycle.mjs +322 -0
- package/scripts/loop/run-queue.mjs +124 -0
- package/scripts/loop/run-refinement-audit.mjs +513 -0
- package/scripts/loop/run-watch-cycle.mjs +358 -0
- package/scripts/loop/steer-loop.mjs +841 -0
- package/scripts/loop/ui-designer-review-contract.mjs +76 -0
- package/scripts/loop/watch-initial-copilot-pr.mjs +253 -0
- package/scripts/projects/add-queue-item.mjs +528 -0
- package/scripts/projects/ensure-queue-board.mjs +837 -0
- package/scripts/projects/list-queue-items.mjs +489 -0
- package/scripts/projects/move-queue-item.mjs +549 -0
- package/scripts/projects/reorder-queue-item.mjs +518 -0
- package/scripts/refine/_refine-helpers.mjs +258 -0
- package/scripts/refine/prose-linkage-detector.mjs +92 -0
- package/scripts/refine/refinement-completeness-checker.mjs +88 -0
- package/scripts/refine/scope-boundary-cross-checker.mjs +163 -0
- package/scripts/refine/tree-integrity-validator.mjs +211 -0
- package/scripts/refine/verify.mjs +178 -0
- package/scripts/repo-wiki-local.mjs +156 -0
- package/scripts/repo-wiki.mjs +119 -0
- package/skills/copilot-pr-followup/SKILL.md +380 -0
- package/skills/dev-loop/SKILL.md +141 -0
- package/skills/dev-loop/scripts/dev-mode-context.mjs +152 -0
- package/skills/dev-loop/scripts/dev-mode-context.test.mjs +80 -0
- package/skills/dev-loop/scripts/init-phase.mjs +71 -0
- package/skills/dev-loop/scripts/log-bash-exit-1.mjs +25 -0
- package/skills/dev-loop/scripts/phase-files.mjs +29 -0
- package/skills/dev-loop/scripts/post-gate-verdict-fallback.mjs +480 -0
- package/skills/dev-loop/scripts/post-gate-verdict-fallback.test.mjs +732 -0
- package/skills/dev-loop/scripts/render-template.mjs +82 -0
- package/skills/dev-loop/scripts/render-template.test.mjs +63 -0
- package/skills/dev-loop/templates/bootstrap-agents.md +26 -0
- package/skills/dev-loop/templates/bootstrap-implementation-state.md +31 -0
- package/skills/dev-loop/templates/bootstrap-implementation-workflow.md +17 -0
- package/skills/dev-loop/templates/dev-mode-retrospective.md +15 -0
- package/skills/dev-loop/templates/dev-mode-review.md +17 -0
- package/skills/dev-loop/templates/dev-mode-skill-changes.md +11 -0
- package/skills/dev-loop/templates/merged-phase-plan.md +19 -0
- package/skills/dev-loop/templates/phase-doc.md +27 -0
- package/skills/dev-loop/templates/phase-summary.md +13 -0
- package/skills/dev-loop/templates/phase-variant.md +15 -0
- package/skills/dev-loop/templates/retrospective.md +11 -0
- package/skills/dev-loop/templates/review.md +32 -0
- package/skills/dev-loop/templates/ui-vision-review.md +55 -0
- package/skills/docs/acceptance-criteria-verification.md +21 -0
- package/skills/docs/anti-patterns.md +21 -0
- package/skills/docs/artifact-authority-contract.md +119 -0
- package/skills/docs/confirmation-rules.md +28 -0
- package/skills/docs/copilot-ci-status-contract.md +52 -0
- package/skills/docs/copilot-loop-operations.md +233 -0
- package/skills/docs/debt-remediation-contract.md +107 -0
- package/skills/docs/entrypoint-strategies.md +115 -0
- package/skills/docs/epic-tree-refinement-procedure.md +234 -0
- package/skills/docs/issue-intake-procedure.md +235 -0
- package/skills/docs/main-agent-contract.md +72 -0
- package/skills/docs/merge-preconditions.md +29 -0
- package/skills/docs/pr-lifecycle-contract.md +209 -0
- package/skills/docs/public-dev-loop-contract.md +497 -0
- package/skills/docs/retrospective-checkpoint-contract.md +159 -0
- package/skills/docs/stop-conditions.md +29 -0
- package/skills/docs/structural-quality.md +42 -0
- package/skills/docs/tracker-first-loop-state.md +281 -0
- package/skills/docs/validation-policy.md +27 -0
- package/skills/docs/workflow-handoff-contract.md +135 -0
- package/skills/final-approval/SKILL.md +19 -0
- package/skills/local-implementation/SKILL.md +640 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copilot PR CI/check normalization contract
|
|
2
|
+
|
|
3
|
+
This document is the canonical bundled contract for deterministic interpretation of PR CI/check inputs used by Copilot PR follow-up flows.
|
|
4
|
+
|
|
5
|
+
Installed skill/runtime consumers should read this bundled `skills/docs/` copy via [Copilot CI Status Contract](../docs/copilot-ci-status-contract.md) from the relevant skill directory. Repository-local docs may summarize or link this contract, but they should not redefine it.
|
|
6
|
+
|
|
7
|
+
Implementation surface:
|
|
8
|
+
- `@dev-loops/core/loop/copilot-ci-status`
|
|
9
|
+
- source file: `packages/core/src/loop/copilot-ci-status.mjs`
|
|
10
|
+
|
|
11
|
+
## Entry points
|
|
12
|
+
|
|
13
|
+
- `normalizeStatusCheckRollupContract(statusCheckRollup)` — normalizes the PR `statusCheckRollup` snapshot from `gh pr view`
|
|
14
|
+
- `normalizeHeadScopedCiContract({ checkRunsStatus, commitStatus })` — normalizes current-head refresh inputs after explicit `check-runs` / commit-status probes
|
|
15
|
+
|
|
16
|
+
Both entry points return the same machine-readable contract shape.
|
|
17
|
+
|
|
18
|
+
## Inputs
|
|
19
|
+
|
|
20
|
+
### `normalizeStatusCheckRollupContract(statusCheckRollup)`
|
|
21
|
+
|
|
22
|
+
- `statusCheckRollup` — the raw PR `statusCheckRollup` array from `gh pr view`; entries may be CheckRun-like (`status` + `conclusion`) or legacy StatusContext-like (`state`)
|
|
23
|
+
|
|
24
|
+
### `normalizeHeadScopedCiContract({ checkRunsStatus, commitStatus })`
|
|
25
|
+
|
|
26
|
+
- `checkRunsStatus` — normalized head-scoped check-runs status (`success` | `failure` | `pending` | `none`)
|
|
27
|
+
- `commitStatus` — normalized head-scoped commit-status status (`success` | `failure` | `pending` | `none`)
|
|
28
|
+
- optional `checkRunsUnsupportedCompleted` — `true` when the current-head check-runs probe observed an unsupported/non-success completed conclusion (for example `CANCELLED`) that must keep the merged result non-green even if commit status separately reports success
|
|
29
|
+
|
|
30
|
+
## Output
|
|
31
|
+
|
|
32
|
+
The returned object always includes:
|
|
33
|
+
|
|
34
|
+
- `overallStatus` (`success` | `failure` | `pending` | `none`)
|
|
35
|
+
- `rollup` (`success`/`failure`/`pending`/`none` booleans; exactly one true)
|
|
36
|
+
- `semantics.wait` (`true` when `overallStatus` is `pending` or `none`)
|
|
37
|
+
- `semantics.blocked` (`true` when `overallStatus` is `failure`)
|
|
38
|
+
- `semantics.timeoutDisposition` (`remain_waiting` for `pending`/`none`; otherwise `not_applicable`)
|
|
39
|
+
|
|
40
|
+
## Deterministic precedence
|
|
41
|
+
|
|
42
|
+
The rollup precedence is fixed and policy-agnostic for ordinary normalized status values:
|
|
43
|
+
1. `failure`
|
|
44
|
+
2. `pending`
|
|
45
|
+
3. `success`
|
|
46
|
+
4. `none`
|
|
47
|
+
|
|
48
|
+
Completed `SKIPPED` and `NEUTRAL` check-run conclusions count as non-blocking success-like signals. A completed `CANCELLED` check does not count as a successful readiness signal by itself; cancelled-only snapshots normalize to `none` so CI-dependent gates do not advance on cancelled work. Legacy successful `StatusContext` rollup entries also normalize to `success` instead of being mistaken for pending work.
|
|
49
|
+
|
|
50
|
+
Merged current-head exception:
|
|
51
|
+
- when `checkRunsUnsupportedCompleted=true`, a `checkRunsStatus: "none"` result caused by unsupported/non-success completed check-runs must remain non-green even if `commitStatus` is `success`
|
|
52
|
+
- in that specific case, the merged `overallStatus` stays `none` rather than letting `success` mask the unsupported completed check-run signal
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Copilot loop operations
|
|
2
|
+
|
|
3
|
+
This document is the canonical operational reference for the deterministic Copilot PR follow-up state machine used by the routed `copilot_pr_followup`, `wait_watch`, `reviewer_fixer`, and `final_approval` paths behind `dev-loop`.
|
|
4
|
+
|
|
5
|
+
Use it together with:
|
|
6
|
+
- [Copilot PR Follow-up Skill](../copilot-pr-followup/SKILL.md)
|
|
7
|
+
- [Public Dev Loop Contract](./public-dev-loop-contract.md)
|
|
8
|
+
- [Retrospective Checkpoint Contract](./retrospective-checkpoint-contract.md) when the current step depends on async start/resume/status or retrospective enforcement
|
|
9
|
+
|
|
10
|
+
## Deterministic orchestration authority
|
|
11
|
+
|
|
12
|
+
When operating in PR follow-up or async watch mode, use the deterministic state machines
|
|
13
|
+
as the authoritative source for:
|
|
14
|
+
|
|
15
|
+
- Copilot follow-up loop: `detect-copilot-loop-state.mjs` from the resolved skill scripts directory
|
|
16
|
+
- reviewer-side PR review loop: `detect-reviewer-loop-state.mjs` from the resolved skill scripts directory
|
|
17
|
+
|
|
18
|
+
Resolve those helper paths from the skill asset layout described by the main skill. In the `dev-loops`
|
|
19
|
+
source repository the skill scripts directory is `../../scripts/` relative to `skills/copilot-pr-followup/SKILL.md`; in normalized
|
|
20
|
+
installed copies it may instead be `scripts/` inside the installed skill directory when that layout bundles the helper scripts.
|
|
21
|
+
|
|
22
|
+
Use the machines to answer:
|
|
23
|
+
- what state the PR/loop is in right now
|
|
24
|
+
- what transitions are currently allowed
|
|
25
|
+
- what the next required action is
|
|
26
|
+
- when to stop instead of guessing
|
|
27
|
+
|
|
28
|
+
Each machine captures an observable snapshot from GitHub facts (plus explicit bounded local loop
|
|
29
|
+
metadata when required) and interprets it into exactly one current state plus allowed next
|
|
30
|
+
transitions. In the `dev-loops` source repository, the supporting source-authority references are [Copilot Loop State Graph](../../docs/copilot-loop-state-graph.md) and [Reviewer Loop State Graph](../../docs/reviewer-loop-state-graph.md) under `../../docs/` relative to `skills/copilot-pr-followup/SKILL.md`. Treat those links as source-repo references, not bundled installed-skill docs.
|
|
31
|
+
|
|
32
|
+
For tracker-first MVP `story -> PR -> tracker sync` work, the source-repo reference is [Tracker-First Story-to-PR Contract](../../docs/tracker-story-pr-contract.md). That source doc inherits source-of-truth ownership, the required work item <-> PR link, and reverse-sync semantics from `#21`; it only adds the mutually exclusive workflow-family states and post-merge sync-verification states for this narrower MVP slice.
|
|
33
|
+
|
|
34
|
+
## Key guarantees from the state machine
|
|
35
|
+
|
|
36
|
+
- `unresolvedThreadCount > 0` always routes to fix/reply-resolve — never to a wait/watch state
|
|
37
|
+
- `snapshot.copilotReviewRequestStatus === "unavailable"` or `snapshot.copilotReviewRequestStatus === "failed"` routes to a terminal stop state — never to sleep or watch
|
|
38
|
+
- `agentFixStatus === "applied"` with unresolved threads routes to `already_fixed_needs_reply_resolve` — reply/resolve on GitHub is required before re-requesting review
|
|
39
|
+
- Copilot being in `requested_reviewers` (`"requested"` or `"already-requested"`) routes to `waiting_for_copilot_review`
|
|
40
|
+
|
|
41
|
+
## How to use the state machine in practice
|
|
42
|
+
|
|
43
|
+
1. Run `node <resolved-skill-scripts>/loop/detect-copilot-loop-state.mjs --repo <owner/name> --pr <number>`
|
|
44
|
+
to get the current Copilot-loop state, decisive snapshot fields, and recommended next action.
|
|
45
|
+
|
|
46
|
+
2. If you already ran `<resolved-skill-scripts>/github/request-copilot-review.mjs` and got a known status,
|
|
47
|
+
inject it without re-probing: add `--review-request-status <status>`.
|
|
48
|
+
|
|
49
|
+
3. When the agent has applied a fix and wants to signal reply/resolve is next, build a snapshot
|
|
50
|
+
with `agentFixStatus: "applied"` and use `--input <snapshot.json>` for interpretation.
|
|
51
|
+
|
|
52
|
+
4. Branch on the detector output instead of inventing a polling loop:
|
|
53
|
+
- `state=waiting_for_copilot_review` with `snapshot.copilotReviewOnCurrentHead=false`: do **not** poll manually; either run `node <resolved-skill-scripts>/loop/run-watch-cycle.mjs --repo <owner/name> --pr <number>` for persistent async waiting or report the wait state and resume later after the single detector call
|
|
54
|
+
- `state=waiting_for_ci` with `snapshot.ciStatus` in `{ "pending", "none" }`: do **not** poll manually by default; use `gh run watch <run-id> --repo <owner/name>` when the current-head run id is already known, otherwise report pending CI and resume later after the single detector refresh. Bounded exception: if GitHub created zero current-head check suites/statuses, the previous head rollup was green, and local `npm run verify` already passed for the same current head, rerun `detect-copilot-loop-state.mjs` with `--local-validation-head-sha <current-head-sha>` so the detector can promote that exact zero-suite case to `snapshot.ciStatus="crediblyGreen"` instead of waiting forever on raw `none`.
|
|
55
|
+
- `snapshot.ciStatus="failure"` remains a stop/fix state, never a wait loop
|
|
56
|
+
|
|
57
|
+
5. For reviewer-side draft-review work, run `node <resolved-skill-scripts>/loop/detect-reviewer-loop-state.mjs --repo <owner/name> --pr <number> [--reviewer-login <login>] [--local-state <path>]`.
|
|
58
|
+
If the state reaches `draft_review_ready`, stage the pending review with
|
|
59
|
+
`node <resolved-skill-scripts>/github/stage-reviewer-draft.mjs --repo <owner/name> --pr <number> --review-file <merged-review.json> --local-state-output <state.json>`,
|
|
60
|
+
then re-run the detector with `--local-state <state.json>`.
|
|
61
|
+
|
|
62
|
+
6. Follow the `nextAction` from the machine output. For stop states (`review_request_unavailable`,
|
|
63
|
+
`blocked_needs_user_decision`), report to the user and do not proceed.
|
|
64
|
+
|
|
65
|
+
## Judgment calls that remain in the agent layer
|
|
66
|
+
|
|
67
|
+
- Whether a comment should be accepted, deferred, or disagreed with
|
|
68
|
+
- Whether the code change is already sufficient (→ sets `agentFixStatus: "applied"`)
|
|
69
|
+
- What the narrowest valid fix is
|
|
70
|
+
- Whether another Copilot pass is desired (→ triggers re-request or selects `done`)
|
|
71
|
+
|
|
72
|
+
## Workflow overview
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
ready issue -> confirm scope -> Copilot branch/PR -> async review/watch -> Pi follow-up fixes -> validation -> confirm verdict/action -> merge when authorized
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Use the resolved `detect-copilot-loop-state.mjs` helper from the skill scripts directory at each
|
|
79
|
+
decision point in this flow to determine the current state and route to the correct next step
|
|
80
|
+
deterministically.
|
|
81
|
+
|
|
82
|
+
## Pre-follow-up working rules
|
|
83
|
+
|
|
84
|
+
> **Phase boundary:** Steps 1-4 apply when no PR exists yet (issue intake).
|
|
85
|
+
> If a PR already exists, skip to [Deterministic orchestration authority](#deterministic-orchestration-authority) —
|
|
86
|
+
> the state machine owns all post-PR routing.
|
|
87
|
+
|
|
88
|
+
### Step 1: Choose the work item
|
|
89
|
+
|
|
90
|
+
Prefer a GitHub issue over an ad hoc local TODO.
|
|
91
|
+
|
|
92
|
+
When selecting the next item:
|
|
93
|
+
- prefer `type:task` issues under the relevant epic
|
|
94
|
+
- prefer `status:ready`
|
|
95
|
+
- inspect milestone, labels, and acceptance criteria
|
|
96
|
+
- confirm whether a PR already exists for the issue before proposing new execution
|
|
97
|
+
|
|
98
|
+
Useful checks:
|
|
99
|
+
- `gh issue list --state open`
|
|
100
|
+
- `gh issue view <number>`
|
|
101
|
+
- `gh pr list --state open`
|
|
102
|
+
|
|
103
|
+
If the user asks for status/progress/readiness/merge-state/next-step (including “what is next”):
|
|
104
|
+
- resolve authoritative active artifact identity first (issue/PR, plus branch/head SHA when useful)
|
|
105
|
+
- for issue targets, do not assert "no open PR" until authoritative issue↔PR linkage is resolved via the startup resolver (`dev-loops loop startup --issue <number>`, run inside the `dev-loop` async subagent) — do not run `detect-linked-issue-pr.mjs` manually
|
|
106
|
+
- resolve artifact state (`open`/`closed`/`merged`/`not_applicable`)
|
|
107
|
+
- resolve current loop state and next action from deterministic helper/state output
|
|
108
|
+
- include explicit resolved artifact identity in the answer
|
|
109
|
+
- if identity/state cannot be resolved confidently, stop with reconcile/unknown instead of guessing from chat context
|
|
110
|
+
|
|
111
|
+
### Step 2: Confirm issue scope before execution
|
|
112
|
+
|
|
113
|
+
Before handing work to Copilot or doing follow-up fixes, summarize:
|
|
114
|
+
- issue number and title
|
|
115
|
+
- parent epic if present
|
|
116
|
+
- milestone
|
|
117
|
+
- labels
|
|
118
|
+
- exact acceptance criteria
|
|
119
|
+
- intended narrow scope
|
|
120
|
+
- non-goals inferred from the issue and plan
|
|
121
|
+
|
|
122
|
+
If the work item is phase-like, ambiguous, or likely to shape more than one downstream step, default to a short fan-out / fan-in refinement pass before implementation:
|
|
123
|
+
- generate 2-3 plan variants in parallel when practical
|
|
124
|
+
- compare the variants explicitly
|
|
125
|
+
- merge them into one bounded execution plan
|
|
126
|
+
- only then proceed with GitHub execution
|
|
127
|
+
|
|
128
|
+
If the issue text is too vague, stop and ask a short clarification question rather than guessing.
|
|
129
|
+
|
|
130
|
+
### Step 3: Decide whether Copilot or Pi should act next
|
|
131
|
+
|
|
132
|
+
Use this heuristic:
|
|
133
|
+
|
|
134
|
+
#### Prefer Copilot when
|
|
135
|
+
- there is a ready implementation issue with clear acceptance criteria
|
|
136
|
+
- no PR exists yet for that issue
|
|
137
|
+
- the user wants the repository's normal GitHub/Copilot path
|
|
138
|
+
- the next step is “start work” rather than “finish this already-open PR right now”
|
|
139
|
+
|
|
140
|
+
#### Prefer Pi follow-up when
|
|
141
|
+
- a PR already exists
|
|
142
|
+
- Copilot has already pushed work and now needs review/fix follow-up
|
|
143
|
+
- there are unresolved comments or failing checks
|
|
144
|
+
- the user wants async in-session watching and response
|
|
145
|
+
|
|
146
|
+
#### Prefer plain analysis only when
|
|
147
|
+
- the user is asking what should happen next
|
|
148
|
+
- authorization for GitHub state changes has not been given yet
|
|
149
|
+
- the issue/PR state is unclear and needs inspection first
|
|
150
|
+
|
|
151
|
+
### Step 4: Copilot handoff rules
|
|
152
|
+
|
|
153
|
+
When preparing work for Copilot:
|
|
154
|
+
- use the GitHub issue as the source of truth
|
|
155
|
+
- preserve the issue's acceptance criteria
|
|
156
|
+
- keep the requested scope narrow
|
|
157
|
+
- do not broaden into adjacent backlog items
|
|
158
|
+
- prefer one issue per PR unless the user explicitly wants bundling
|
|
159
|
+
|
|
160
|
+
Before any GitHub mutation such as assigning the issue, posting instructions, or changing labels, confirm first unless explicitly authorized.
|
|
161
|
+
|
|
162
|
+
When you do hand work to Copilot:
|
|
163
|
+
- assign `copilot-swe-agent`
|
|
164
|
+
- reference the issue number and acceptance criteria clearly
|
|
165
|
+
- keep instructions implementation-focused and test-aware
|
|
166
|
+
|
|
167
|
+
## PR description contract
|
|
168
|
+
|
|
169
|
+
Follow the PR description contract (see [Agent Instructions](../../AGENTS.md) if present; otherwise use the structure below): detailed structured descriptions, not thin placeholders. At minimum include change summary, scope/context, explicit acceptance criteria, explicit definition of done, and explicit non-goals, and `Closes #N` (or `Fixes #N`) for the linked issue so GitHub auto-closes it on merge.
|
|
170
|
+
|
|
171
|
+
Checkbox rule: acceptance criteria, definition-of-done items, and any task list must be rendered as real GitHub markdown checkboxes inside list items (`- [ ]` / `- [x]`, also `* [ ]` / `* [x]`). Do not wrap checkbox markers (e.g. `[x]`) in backticks. Do not place checkbox markers inside table cells — task lists are not interactive there even with a leading `- `.
|
|
172
|
+
|
|
173
|
+
New PRs in this workflow must be opened as **draft** PRs first when the repository enables `.devloops` at repo root `workflow.requireDraftFirst`. The built-in shipped default remains permissive; this repo opts in. Do not create a fresh PR directly in ready-for-review state unless the user explicitly overrides that policy for the current PR scope. The draft gate inspection is a real workflow boundary, so a new PR must exist in draft before `gh pr ready` is even eligible.
|
|
174
|
+
|
|
175
|
+
Only use `node <resolved-skill-scripts>/github/create-draft-pr.mjs` when authoritative issue↔PR resolution says there is no already-open linked PR. If a PR already exists, reuse/update that canonical PR instead of opening another one. This wrapper preserves the underlying `gh pr create` output contract while enforcing draft-first mechanically.
|
|
176
|
+
|
|
177
|
+
MUST use `node <resolved-skill-scripts>/github/create-draft-pr.mjs --repo <owner/name> --assignee @me --base <base> --head <head> --title "..." --body-file <body-file>`.
|
|
178
|
+
|
|
179
|
+
## Timeout and watch policy
|
|
180
|
+
|
|
181
|
+
This workflow is intentionally long-lived, but one Copilot review watch boundary must still be capped.
|
|
182
|
+
|
|
183
|
+
Preferred defaults for this repo:
|
|
184
|
+
- poll interval for review/activity watchers: **1 minute** (derived from `packages/core/src/loop/policy-constants.mjs` DEFAULT_POLL_INTERVAL_MS)
|
|
185
|
+
- max watch timeout per Copilot review boundary: **30 minutes** (derived from `packages/core/src/loop/policy-constants.mjs` COPILOT_REVIEW_WAIT_TIMEOUT_MS)
|
|
186
|
+
- if that 30-minute watch budget expires, refresh authoritative state once; if the refreshed state still resolves `waiting_for_copilot_review`, stop with `watch timeout — PR #<number> needs manual attention`
|
|
187
|
+
- do not silently extend that 30-minute cap unless the user or conductor explicitly authorizes a longer watch budget for the active PR
|
|
188
|
+
- parent/subagent no-activity threshold for watcher-style runs: at least **15 minutes**
|
|
189
|
+
- active-long-running notice threshold for watcher-style runs: about **30 minutes**
|
|
190
|
+
|
|
191
|
+
These are the defaults built into `probe-copilot-review.mjs`, `run-watch-cycle.mjs`, and the `watchArgs` emitted by `copilot-pr-handoff.mjs`. Do not pass removed CLI policy flags (`--poll-interval-ms`, `--timeout-ms`, `--probe-only`) — helpers hard-error when they are provided. Timeouts and intervals are derived from `packages/core/src/loop/policy-constants.mjs`.
|
|
192
|
+
|
|
193
|
+
### Outer-loop checkpoint: canonical re-attachment artifact
|
|
194
|
+
|
|
195
|
+
The outer-loop checkpoint (`tmp/copilot-loop/<owner>/<repo>/pr-<n>/outer-loop-state.json`)
|
|
196
|
+
is the canonical re-attachment artifact for async subagent runs. It is written by
|
|
197
|
+
`outer-loop.mjs` at every conductor cycle and records:
|
|
198
|
+
|
|
199
|
+
| Field | Meaning |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `pr` | PR number |
|
|
202
|
+
| `repo` | Repository slug (`owner/name`; lowercased by `outer-loop.mjs`) |
|
|
203
|
+
| `outerAction` | Next action: `continue_wait`, `reenter_copilot_loop`, `reenter_reviewer_loop`, `stop`, `done` |
|
|
204
|
+
| `copilotState` | Current copilot inner-loop state |
|
|
205
|
+
| `reviewerState` | Current reviewer inner-loop state |
|
|
206
|
+
| `reviewerScope` | Reviewer scope mode (always present; e.g. `all_reviewers` or `single_reviewer`) |
|
|
207
|
+
| `reviewerLogin` | Reviewer GitHub login (always present; `null` unless single-reviewer scope) |
|
|
208
|
+
| `reason` | Stop reason (`null` when `outerAction` is not `stop`) |
|
|
209
|
+
| `timestamp` | ISO 8601 timestamp of checkpoint write |
|
|
210
|
+
| `waitCycles` | Number of wait cycles accumulated |
|
|
211
|
+
| `headSha` | PR head SHA at checkpoint time (`null` when unavailable) |
|
|
212
|
+
|
|
213
|
+
### Re-attachment contract
|
|
214
|
+
|
|
215
|
+
When a fresh `dev-loop` async subagent starts on a PR that already has an outer-loop
|
|
216
|
+
checkpoint, it must read the checkpoint before entering any intake or follow-up procedure:
|
|
217
|
+
|
|
218
|
+
1. If `outerAction` is `continue_wait` or `reenter_copilot_loop`: auto-resume the loop
|
|
219
|
+
rather than treating the start as fresh intake.
|
|
220
|
+
2. If `outerAction` is `reenter_reviewer_loop`: enter the reviewer-loop path.
|
|
221
|
+
3. If `outerAction` is `stop`: the loop is blocked or needs a human decision; report the `reason` and ask for direction.
|
|
222
|
+
4. If no checkpoint or `outerAction` is `done`: `done` means the PR is merged/closed; normal fresh startup.
|
|
223
|
+
|
|
224
|
+
The checkpoint is the only source of truth for re-attachment. Do not rely on chat context
|
|
225
|
+
or local notes to determine "where we left off."
|
|
226
|
+
|
|
227
|
+
## Hard rule: no agent-authored shell polling
|
|
228
|
+
|
|
229
|
+
Helper-owned sleep inside `run-watch-cycle.mjs`, `probe-copilot-review.mjs`, or `watch-initial-copilot-pr.mjs` is allowed. Agent-authored shell polling (`sleep`, `for`, `while`, `timeout` wrappers around tool invocations) is a contract breach. This rule applies to ALL repos using the dev-loop workflow, not just the source repo.
|
|
230
|
+
|
|
231
|
+
A watcher sleeping between polls is expected behavior, not a blocker.
|
|
232
|
+
|
|
233
|
+
If the polling interval is 1 minute, do not treat silence shorter than one full poll interval as suspicious, and do not configure needs-attention thresholds close to a few seconds for this loop.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Debt remediation contract
|
|
2
|
+
|
|
3
|
+
Canonical authority for the debt remediation pipeline and its integration with the `dev-loop` execution path.
|
|
4
|
+
|
|
5
|
+
## Pipeline
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
debt_signals → cluster → score → shape → remediation_item → GitHub issue → dev-loop
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Core pipeline stages under `packages/core/src/debt/`:
|
|
12
|
+
|
|
13
|
+
| Module | Role | Side effects |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `debt-signal.mjs` | Signal schema and validation | None |
|
|
16
|
+
| `cluster.mjs` | Group signals into findings by file, module, theme | None |
|
|
17
|
+
| `score.mjs` | 0-100 score from frequency, severity, impact | None |
|
|
18
|
+
| `shape.mjs` | Classify findings: remediation_item, debt_epic, defer, watch, dismiss | None |
|
|
19
|
+
| `remediation-to-issue.mjs` | Convert remediation_item to GitHub issue payload; create via `gh issue create` | `gh issue create` call |
|
|
20
|
+
|
|
21
|
+
The cluster, score, and shape stages are deterministic pure functions.
|
|
22
|
+
`remediation-to-issue.mjs` performs a side effect (`gh issue create`) and requires GitHub auth.
|
|
23
|
+
|
|
24
|
+
## CLI entrypoint
|
|
25
|
+
|
|
26
|
+
`scripts/loop/debt-remediate.mjs` is the single CLI entrypoint routed under `dev-loops loop debt-remediate`.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
dev-loops loop debt-remediate --input <signals.json> [--repo <owner/name>] [--dry-run]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Contract
|
|
33
|
+
|
|
34
|
+
- **Input**: JSON array of `debt_signal` objects (validated against `DebtSignalSchema`)
|
|
35
|
+
- **Pipeline**: cluster → score → shape → issue creation
|
|
36
|
+
- **Issue creation**: calls `gh issue create --assignee @me` for each `remediation_item`
|
|
37
|
+
- **Output**: JSON report with counts, issue URLs, and summary
|
|
38
|
+
- **Exit codes**: 0 (success — all remediation issue creations succeeded), 1 (argument error, input validation failure, or any issue creation failure)
|
|
39
|
+
- **Dry run**: `--dry-run` runs the full pipeline and validates but skips issue creation
|
|
40
|
+
|
|
41
|
+
### Output shape
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"ok": true,
|
|
46
|
+
"dryRun": false,
|
|
47
|
+
"repo": "owner/name",
|
|
48
|
+
"signals": 5,
|
|
49
|
+
"findings": 2,
|
|
50
|
+
"remediationItems": 1,
|
|
51
|
+
"debtEpics": 0,
|
|
52
|
+
"deferred": 1,
|
|
53
|
+
"watching": 0,
|
|
54
|
+
"dismissed": 0,
|
|
55
|
+
"issues": [
|
|
56
|
+
{
|
|
57
|
+
"findingId": "uuid",
|
|
58
|
+
"title": "...",
|
|
59
|
+
"created": true,
|
|
60
|
+
"issueNumber": 123,
|
|
61
|
+
"issueUrl": "https://github.com/owner/name/issues/123",
|
|
62
|
+
"error": null
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"summary": "5 signals → 2 findings; 1 remediation items (1 issues created, 0 failed); ..."
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Integration with dev-loop
|
|
70
|
+
|
|
71
|
+
Once a remediation issue is created, it is a standard GitHub issue that feeds into the existing `dev-loop` execution path:
|
|
72
|
+
|
|
73
|
+
1. `dev-loops loop startup --issue <n>` resolves the issue
|
|
74
|
+
2. Standard `copilot-pr-followup` or `issue_intake` strategy takes over
|
|
75
|
+
3. PR → review → merge as normal
|
|
76
|
+
|
|
77
|
+
This closes the remediation execution loop: `remediation_item → issue → dev-loop → PR → merge`.
|
|
78
|
+
|
|
79
|
+
## Shape thresholds
|
|
80
|
+
|
|
81
|
+
Thresholds are hardcoded constants in `shape.mjs`. The outcome for a finding is determined by the combined thresholds:
|
|
82
|
+
|
|
83
|
+
| Threshold | Value | Outcome |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `EPIC_SIGNAL_COUNT_THRESHOLD` | 3 | When `signalCount > 3` and score ≥ `ITEM_THRESHOLD`, the finding becomes a `debt_epic` instead of `remediation_item` |
|
|
86
|
+
| `ITEM_THRESHOLD` | 65 | `remediation_item` (unless signal count pushes to `debt_epic`) |
|
|
87
|
+
| `DEFER_THRESHOLD` | 50 | `defer` |
|
|
88
|
+
| `WATCH_THRESHOLD` | 30 | `watch` |
|
|
89
|
+
| (below) | <30 | `dismiss` |
|
|
90
|
+
|
|
91
|
+
The `EPIC_SIGNAL_COUNT_THRESHOLD` takes precedence: a finding with score ≥ `ITEM_THRESHOLD` and `signalCount > 3` becomes a `debt_epic`, not a `remediation_item`.
|
|
92
|
+
|
|
93
|
+
## Scoring model
|
|
94
|
+
|
|
95
|
+
Three dimensions, weighted:
|
|
96
|
+
|
|
97
|
+
| Dimension | Weight | Description |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| Frequency | 0.35 | Signal count, logarithmic cap |
|
|
100
|
+
| Severity | 0.40 | Average severity hint (info=1..critical=5) |
|
|
101
|
+
| Impact | 0.25 | File presence, confidence, category diversity |
|
|
102
|
+
|
|
103
|
+
Clamped to 0-100.
|
|
104
|
+
|
|
105
|
+
## Labels
|
|
106
|
+
|
|
107
|
+
Created issues receive the `workflow` label by default. This keeps them discoverable in the standard dev-loop issue tracking surface.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Entrypoint strategies
|
|
2
|
+
|
|
3
|
+
This document replaces the seven individual `entrypoint-briefing-*.md` files with a single per-strategy-section reference. Each section preserves the state vocabulary and key operational content for that strategy.
|
|
4
|
+
|
|
5
|
+
## Copilot PR follow-up
|
|
6
|
+
|
|
7
|
+
State vocabulary: `waiting_for_initial_copilot_implementation`, `waiting_for_copilot_review`, `review_feedback_received`, `linked_pr_ready_for_followup`, `blocked_needs_user_decision`
|
|
8
|
+
|
|
9
|
+
Next-action sentence: "Load PR state from `detect-copilot-loop-state.mjs`, resolve gate coordination, then execute the appropriate follow-up action (fix, review, wait, or escalate)."
|
|
10
|
+
|
|
11
|
+
Helpers to run first:
|
|
12
|
+
1. `dev-loops loop loop-state --repo <owner/name> --pr <N>` — resolve loop state
|
|
13
|
+
2. `dev-loops loop gate-coordination --repo <owner/name> --pr <N>` — resolve gate state
|
|
14
|
+
3. `dev-loops gate upsert-verdict` — post/update gate comments
|
|
15
|
+
|
|
16
|
+
Required reading:
|
|
17
|
+
- [Public Dev Loop Contract](public-dev-loop-contract.md)
|
|
18
|
+
- [Copilot Loop Operations](copilot-loop-operations.md)
|
|
19
|
+
- [Confirmation rules](confirmation-rules.md)
|
|
20
|
+
- [Stop conditions](stop-conditions.md)
|
|
21
|
+
- [Validation policy](validation-policy.md)
|
|
22
|
+
|
|
23
|
+
## External PR follow-up
|
|
24
|
+
|
|
25
|
+
State vocabulary: Same as Copilot PR follow-up but with external-human ownership.
|
|
26
|
+
|
|
27
|
+
Next-action sentence: "Load PR state, check for external review cycles, then route to reviewer/fixer or maintenance workflow."
|
|
28
|
+
|
|
29
|
+
Helpers to run first: Same as [Copilot PR follow-up](#copilot-pr-follow-up).
|
|
30
|
+
|
|
31
|
+
Required reading: Same as [Copilot PR follow-up](#copilot-pr-follow-up).
|
|
32
|
+
|
|
33
|
+
## Final approval
|
|
34
|
+
|
|
35
|
+
State vocabulary: `approval_ready`, `merge_ready`, `waiting_for_merge_authorization`
|
|
36
|
+
|
|
37
|
+
Next-action sentence: "Verify pre_approval_gate evidence, confirm CI green + resolved threads, then request explicit merge authorization."
|
|
38
|
+
|
|
39
|
+
Helpers to run first:
|
|
40
|
+
1. `dev-loops gate detect-evidence --repo <owner/name> --pr <N>` — verify gate evidence
|
|
41
|
+
2. `dev-loops gate upsert-verdict` — post pre_approval_gate
|
|
42
|
+
|
|
43
|
+
Required reading:
|
|
44
|
+
- [Public Dev Loop Contract](public-dev-loop-contract.md)
|
|
45
|
+
- [Final Approval SKILL](../final-approval/SKILL.md)
|
|
46
|
+
- [Merge preconditions](merge-preconditions.md)
|
|
47
|
+
- [Confirmation rules](confirmation-rules.md)
|
|
48
|
+
|
|
49
|
+
## Issue intake
|
|
50
|
+
|
|
51
|
+
State vocabulary: `waiting_for_initial_copilot_implementation`, `needs_refinement`, `ready_needs_assignment_confirmation`, `ready_assign_now`, `assigned_to_copilot`
|
|
52
|
+
|
|
53
|
+
Next-action sentence: "Resolve issue readiness, handle assignment seam, then bootstrap PR creation or wait for Copilot implementation."
|
|
54
|
+
|
|
55
|
+
Helpers to run first:
|
|
56
|
+
1. `dev-loops loop linked-issue-pr --repo <owner/name> --issue <N>` — resolve issue↔PR linkage
|
|
57
|
+
2. `dev-loops loop startup` — resolve routing
|
|
58
|
+
|
|
59
|
+
Required reading:
|
|
60
|
+
- [Public Dev Loop Contract](public-dev-loop-contract.md)
|
|
61
|
+
- [Issue Intake Procedure](issue-intake-procedure.md)
|
|
62
|
+
- [Confirmation rules](confirmation-rules.md)
|
|
63
|
+
- [Stop conditions](stop-conditions.md)
|
|
64
|
+
|
|
65
|
+
## Local implementation
|
|
66
|
+
|
|
67
|
+
State vocabulary: `local_branch`, `local_phase`, `in_progress`, `review`, `merge_ready`
|
|
68
|
+
|
|
69
|
+
Next-action sentence: "Fan-out refinement (unless light-mode), implement phase, validate, then create PR or continue to next phase."
|
|
70
|
+
|
|
71
|
+
Helpers to run first:
|
|
72
|
+
1. `dev-loops loop startup` — resolve routing
|
|
73
|
+
2. `node scripts/loop/pre-commit-branch-guard.mjs --expected-branch <name> [--require-worktree] [--block-main-checkout]` — verify isolation (no CLI route; use script path)
|
|
74
|
+
|
|
75
|
+
Required reading:
|
|
76
|
+
- [Public Dev Loop Contract](public-dev-loop-contract.md)
|
|
77
|
+
- [Local Implementation SKILL](../local-implementation/SKILL.md)
|
|
78
|
+
- [Anti-patterns](anti-patterns.md)
|
|
79
|
+
- [Structural quality](structural-quality.md)
|
|
80
|
+
- [Validation policy](validation-policy.md)
|
|
81
|
+
|
|
82
|
+
## Tracker-first
|
|
83
|
+
|
|
84
|
+
**Strategy:** `tracker_first` (reserved for future `dev-loop` routing when tracker context detected)
|
|
85
|
+
|
|
86
|
+
**Purpose:** Tracker-first workflow for story/epic tracker items that follow a PR-based GitHub execution path.
|
|
87
|
+
|
|
88
|
+
**Routing status:** Routing integration in `resolve-dev-loop-startup.mjs` is deferred (no `tracker_first` route exists yet). This briefing documents the intended contract surface; the state machine and detector are implemented and tested.
|
|
89
|
+
|
|
90
|
+
**Key artifacts:**
|
|
91
|
+
- Tracker issue (canonical spec)
|
|
92
|
+
- [Tracker-First Loop State](tracker-first-loop-state.md) — state machine doc
|
|
93
|
+
- `detect-tracker-first-loop-state.mjs` — loop state detector
|
|
94
|
+
- `detect-tracker-pr-state.mjs` — PR-level state detector
|
|
95
|
+
|
|
96
|
+
**Routing:** `dev-loop` will resolve to tracker-first when a tracker context is detected (issue has tracker labels, is a tracker-backed issue). Fail-closed: unknown tracker state → `needs_triage`.
|
|
97
|
+
|
|
98
|
+
**State vocabulary:** `drafting`, `needs_triage`, `in_progress`, `in_review`, `merge_ready`, `blocked`, `completed`, `unknown`
|
|
99
|
+
|
|
100
|
+
**Interface contract:** Same as Copilot loop: `{ ok, state, snapshot, allowedTransitions, nextAction }`
|
|
101
|
+
|
|
102
|
+
## Wait / watch
|
|
103
|
+
|
|
104
|
+
State vocabulary: `waiting`, `waiting_for_initial_copilot_implementation`, `waiting_for_copilot_review`
|
|
105
|
+
|
|
106
|
+
Next-action sentence: "Enter healthy-watch mode with configured timeout; escalate only on genuine blocked/authorization/reconcile states."
|
|
107
|
+
|
|
108
|
+
Helpers to run first:
|
|
109
|
+
1. `dev-loops loop watch-initial --repo <owner/name> --issue <N>` — bootstrap watcher
|
|
110
|
+
2. `dev-loops loop watch-cycle --repo <owner/name> --pr <N>` — cycle watcher
|
|
111
|
+
|
|
112
|
+
Required reading:
|
|
113
|
+
- [Public Dev Loop Contract](public-dev-loop-contract.md)
|
|
114
|
+
- [Copilot Loop Operations](copilot-loop-operations.md)
|
|
115
|
+
- [Stop conditions](stop-conditions.md)
|