Skip to content

Commit 613f7aa

Browse files
ScottArbeitScott Arbeit
andauthored
Continuous Review, Work Items, and Refinery-Grade Promotion Queues (#47)
* Add continuous review foundation layers * Add work item CLI commands * Add review CLI commands * Add queue CLI commands * Add determinism and queue tests * Add continuous review tests and docs * Update beads tracking * bd sync: 2026-01-06 21:10:01 * Close Grace-7it epic * Update beads metadata * Fix enqueue to reuse parsed parameters * Scope event envelopes to repository ids * Fix verbose parse output and review event match --------- Co-authored-by: Scott Arbeit <scottarbeit@github.com>
1 parent 559a3af commit 613f7aa

File tree

75 files changed

+9712
-51
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+9712
-51
lines changed

.beads/issues.jsonl

Lines changed: 47 additions & 0 deletions
Large diffs are not rendered by default.

.beads/last-touched

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Grace-4g4

.beads/metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"database": "beads.db",
33
"jsonl_export": "issues.jsonl",
4-
"last_bd_version": "0.29.0"
4+
"last_bd_version": "0.40.0"
55
}

docs/Continuous review.md

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
2+
# Continuous review
3+
4+
Continuous review is the system that tracks candidates for promotion, evaluates
5+
risk, records review artifacts, and provides a control plane for gates and
6+
required actions. It is designed to make review deterministic and auditable
7+
while still allowing humans and agents to step in when needed.
8+
9+
At a high level, the flow is: policy defines expectations, Stage 0 analysis
10+
records deterministic signals, candidates are enqueued for promotion, gates and
11+
review packets provide evidence and findings, and checkpoints record how far
12+
review has progressed.
13+
14+
## Big picture concepts
15+
16+
- A policy snapshot is an immutable, hashed set of rules for a target branch.
17+
- A Stage 0 analysis captures deterministic signals for a reference.
18+
- A promotion queue orders candidates that want to land on a target branch.
19+
- An integration candidate represents one promotion attempt and tracks its
20+
status and required actions.
21+
- Review packets summarize findings, evidence, and chaptering for a candidate.
22+
- Review checkpoints record how far a reviewer has read through references.
23+
- Gates are discrete checks (policy, review, build/test) that produce
24+
attestations.
25+
26+
## Key building blocks
27+
28+
### Policy snapshots
29+
30+
Policy snapshots are immutable rule bundles associated with a target branch. The
31+
`PolicySnapshotId` is a SHA256 hash of the policy contents plus the parser
32+
version. They are used by the queue, gates, Stage 0 analysis, and review
33+
analysis to ensure deterministic inputs.
34+
35+
Current policy endpoints:
36+
37+
- `POST /policy/current` returns the active snapshot for a target branch.
38+
- `POST /policy/acknowledge` records an acknowledgement for a snapshot.
39+
40+
### Stage 0 analysis
41+
42+
Stage 0 is the deterministic, non-model analysis layer. When a reference of type
43+
Commit, Checkpoint, or Promotion is created, the server records a Stage 0
44+
analysis with a deterministic risk profile. Today, that profile is the default
45+
structure populated with the reference ID, policy snapshot ID (if available),
46+
and a timestamp. It is persisted through the Stage0 actor and can be read
47+
internally for later analysis.
48+
49+
### Promotion queue
50+
51+
Each target branch has a promotion queue that stores the list of candidate IDs
52+
and the current queue state.
53+
54+
Queue state values:
55+
56+
- `Idle`
57+
- `Running`
58+
- `Paused`
59+
- `Degraded`
60+
61+
Queues are created implicitly on first enqueue. Initialization requires a policy
62+
snapshot ID; if the queue does not exist and you enqueue without a policy
63+
snapshot, the server rejects the request.
64+
65+
### Integration candidates
66+
67+
An integration candidate is the unit of work that moves through continuous
68+
review. It captures the target branch, optional work item, policy snapshot,
69+
status, and any required actions, conflicts, gate attestations, and review
70+
packet linkage.
71+
72+
Candidate status values:
73+
74+
- `Pending`
75+
- `Ready`
76+
- `Running`
77+
- `Blocked`
78+
- `Failed`
79+
- `Succeeded`
80+
- `Quarantined`
81+
- `Canceled`
82+
83+
Candidates are created when you enqueue a candidate ID that does not yet exist.
84+
85+
### Gates and gate attestations
86+
87+
Gates are named checks with a definition (name, version, execution mode).
88+
Running a gate produces a GateAttestation that records the result, timestamp,
89+
and metadata. Gate attestations are stored in their own actor and referenced by
90+
the candidate.
91+
92+
Built-in gates today:
93+
94+
- `policy` (synchronous): passes if a policy snapshot exists, blocks otherwise.
95+
- `review` (synchronous): stub, currently always passes.
96+
- `build-test` (async callback): stub, currently returns `Skipped`.
97+
98+
### Evidence selection
99+
100+
Evidence selection uses a deterministic budgeted selector to build slices from a
101+
diff. It supports redaction patterns and scores slices based on change magnitude
102+
and Stage 0 signals such as sensitive paths and dependency config changes. The
103+
resulting EvidenceSetSummary is used for chaptering and model analysis receipts.
104+
105+
### Review packets
106+
107+
A review packet is the primary artifact for a candidate review. It contains
108+
summary text, chapters, findings, optional evidence summaries, and optional gate
109+
summaries. Chapters are built deterministically by grouping paths on the top-
110+
level folder segment. The chapter ID is a SHA256 hash of the ordered path list.
111+
112+
Review packets are stored in the Review actor through `UpsertPacket` events.
113+
There is no public endpoint for upserting packets yet, so review packets are
114+
typically created by internal processes.
115+
116+
### Review checkpoints
117+
118+
Review checkpoints store how far a reviewer has read through references for a
119+
candidate or promotion group. A checkpoint includes the reviewer, reviewed-up-to
120+
reference ID, and policy snapshot ID.
121+
122+
### Required actions
123+
124+
Required actions are machine-readable tasks attached to a candidate, such as
125+
`AcknowledgePolicyChange` or `ResolveConflict`. The server recomputes required
126+
actions on demand and updates the candidate if the computed list differs from
127+
the stored list.
128+
129+
The current required-actions logic adds:
130+
131+
- `AcknowledgePolicyChange` if the candidate has no policy snapshot ID.
132+
- `ResolveConflict` if conflicts are present.
133+
- `RunGate` if the candidate is `Blocked`.
134+
- `FixGateFailure` if the candidate is `Failed`.
135+
136+
## End-to-end flow (today)
137+
138+
1) A reference (commit/checkpoint/promotion) is created.
139+
2) Stage 0 analysis is recorded with a deterministic risk profile.
140+
3) A candidate is enqueued for a target branch.
141+
4) The promotion queue is initialized (if needed) with a policy snapshot ID.
142+
5) The candidate can be queried, its required actions computed, and gates rerun
143+
on demand.
144+
6) Review packets and findings can be read (if they exist) and findings can be
145+
resolved.
146+
7) Review checkpoints can be recorded as reviewers progress.
147+
148+
Note: queue processing and gate execution orchestration are not currently
149+
automatic in the server; they are expected to be driven by external services or
150+
manual commands.
151+
152+
## API surface
153+
154+
### Queue and candidate endpoints
155+
156+
- `POST /queue/status`
157+
- `POST /queue/enqueue`
158+
- `POST /queue/pause`
159+
- `POST /queue/resume`
160+
- `POST /queue/dequeue`
161+
- `POST /candidate/get`
162+
- `POST /candidate/cancel`
163+
- `POST /candidate/retry`
164+
- `POST /candidate/required-actions`
165+
- `POST /candidate/attestations`
166+
- `POST /candidate/gate/rerun`
167+
168+
Example: enqueue a candidate.
169+
170+
```json
171+
{
172+
"TargetBranchId": "8c6f3b1b-53b1-4a1b-84fd-9c8b5a4e2e11",
173+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
174+
"PolicySnapshotId": "e3b0c44298fc1c149afbf4c8996fb924",
175+
"WorkItemId": "f88b46e2-5c36-4b52-9e36-716f7d7a9a8b",
176+
"PromotionGroupId": "3d5c4d9a-0123-4567-89ab-987654321000",
177+
"CorrelationId": "corr-1001"
178+
}
179+
```
180+
181+
Example: fetch required actions for a candidate.
182+
183+
```json
184+
{
185+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
186+
"CorrelationId": "corr-1002"
187+
}
188+
```
189+
190+
Example: rerun a gate.
191+
192+
```json
193+
{
194+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
195+
"GateName": "policy",
196+
"CorrelationId": "corr-1003"
197+
}
198+
```
199+
200+
### Review endpoints
201+
202+
- `POST /review/packet`
203+
- `POST /review/checkpoint`
204+
- `POST /review/resolve`
205+
- `POST /review/deepen` (stub, not implemented)
206+
207+
Example: open a review packet for a candidate.
208+
209+
```json
210+
{
211+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
212+
"CorrelationId": "corr-2001"
213+
}
214+
```
215+
216+
Example: record a review checkpoint.
217+
218+
```json
219+
{
220+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
221+
"ReviewedUpToReferenceId": "f12a0d31-0d5a-4a5f-a5a7-3d2c3a9f5b2c",
222+
"PolicySnapshotId": "e3b0c44298fc1c149afbf4c8996fb924",
223+
"CorrelationId": "corr-2002"
224+
}
225+
```
226+
227+
Example: resolve a finding.
228+
229+
```json
230+
{
231+
"CandidateId": "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
232+
"FindingId": "6e58b4de-7f3b-4a2b-9a6f-111111111111",
233+
"ResolutionState": "Approved",
234+
"Note": "Reviewed and acceptable.",
235+
"CorrelationId": "corr-2003"
236+
}
237+
```
238+
239+
### Policy endpoints
240+
241+
- `POST /policy/current`
242+
- `POST /policy/acknowledge`
243+
244+
Example: acknowledge a policy snapshot.
245+
246+
```json
247+
{
248+
"TargetBranchId": "8c6f3b1b-53b1-4a1b-84fd-9c8b5a4e2e11",
249+
"PolicySnapshotId": "e3b0c44298fc1c149afbf4c8996fb924",
250+
"Note": "Reviewed for Q1 rollout",
251+
"CorrelationId": "corr-3001"
252+
}
253+
```
254+
255+
## CLI examples
256+
257+
Queue a candidate (initialize queue with policy snapshot if needed):
258+
259+
```powershell
260+
./grace queue enqueue `
261+
--candidate 4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c `
262+
--branch main `
263+
--policy-snapshot-id e3b0c44298fc1c149afbf4c8996fb924 `
264+
--work f88b46e2-5c36-4b52-9e36-716f7d7a9a8b
265+
```
266+
267+
Check queue status:
268+
269+
```powershell
270+
./grace queue status --branch main
271+
```
272+
273+
Pause and resume the queue:
274+
275+
```powershell
276+
./grace queue pause --branch main
277+
./grace queue resume --branch main
278+
```
279+
280+
Retry a candidate:
281+
282+
```powershell
283+
./grace queue retry `
284+
--candidate 4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c `
285+
--branch main
286+
```
287+
288+
Open a review packet:
289+
290+
```powershell
291+
./grace review open --candidate 4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c
292+
```
293+
294+
Record a review checkpoint:
295+
296+
```powershell
297+
./grace review checkpoint `
298+
--candidate 4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c `
299+
--reference f12a0d31-0d5a-4a5f-a5a7-3d2c3a9f5b2c
300+
```
301+
302+
Resolve a finding:
303+
304+
```powershell
305+
./grace review resolve `
306+
--candidate 4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c `
307+
--finding-id 6e58b4de-7f3b-4a2b-9a6f-111111111111 `
308+
--approve `
309+
--note "Reviewed and acceptable."
310+
```
311+
312+
## SDK examples
313+
314+
Fetch a candidate and required actions (F#):
315+
316+
```fsharp
317+
open Grace.SDK
318+
open Grace.Shared.Parameters.Queue
319+
320+
let candidateParams =
321+
CandidateParameters(
322+
CandidateId = "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
323+
CorrelationId = "corr-1002"
324+
)
325+
let! candidate = Candidate.Get(candidateParams)
326+
327+
let actionsParams =
328+
CandidateParameters(
329+
CandidateId = "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
330+
CorrelationId = "corr-1002"
331+
)
332+
let! actions = Candidate.RequiredActions(actionsParams)
333+
```
334+
335+
Open a review packet (F#):
336+
337+
```fsharp
338+
open Grace.SDK
339+
open Grace.Shared.Parameters.Review
340+
341+
let reviewParams =
342+
GetReviewPacketParameters(
343+
CandidateId = "4fe3c2a9-35f0-4dc2-9f8b-4d3e2f1a0b9c",
344+
CorrelationId = "corr-2001"
345+
)
346+
let! packet = Review.GetPacket(reviewParams)
347+
```
348+
349+
## Deterministic chaptering and baseline drift
350+
351+
- Chaptering groups files by their top-level folder segment (e.g.,
352+
`src/api/foo.cs` and `src/api/bar.cs` live in the `src` chapter).
353+
- Chapter IDs are a SHA256 hash of the sorted path list for that chapter.
354+
- Baseline drift evaluation exists as a shared helper and compares churn totals
355+
against policy thresholds (`ChurnLines`, `FilesTouched`). It returns affected
356+
paths, chapters, and findings. The helper is not yet wired into queue-required
357+
actions.
358+
359+
## Current limitations and stubs
360+
361+
- Review packets cannot be created via public APIs yet; they are stored only
362+
through internal actor commands.
363+
- `review/deepen` is a placeholder and returns a not-implemented error.
364+
- `review inbox` and `review delta` CLI commands are stubs.
365+
- Gate implementations are mostly stubbed (review/build-test) and return static
366+
results.
367+
- Stage 0 analysis currently records default risk profiles; deeper deterministic
368+
analysis is not wired yet.
369+
- Queue processing and automatic candidate state transitions are not implemented
370+
in the server.
371+
- Promotion-group review packets are not supported by the CLI yet; it accepts
372+
`--promotion-group` but errors if used.

0 commit comments

Comments
 (0)