devflow-kit 2.1.0 → 2.3.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/CHANGELOG.md +33 -0
- package/dist/commands/resolve.md +29 -16
- package/package.json +1 -1
- package/src/assets/agents/learning.md +63 -13
- package/src/assets/agents/skim.md +12 -5
- package/src/assets/agents/triage.md +19 -1
- package/src/assets/commands/resolve.mds +29 -16
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +1 -0
- package/src/assets/scripts/hooks/background-memory-update +180 -37
- package/src/assets/scripts/hooks/is-hex-sha +14 -0
- package/src/assets/scripts/hooks/json-helper.cjs +223 -38
- package/src/assets/scripts/hooks/lib/decisions-format.cjs +264 -43
- package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +1 -1
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +59 -28
- package/src/assets/scripts/hooks/pre-compact-memory +40 -22
- package/src/assets/scripts/hooks/session-start-memory +19 -20
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,37 @@ All notable changes to Devflow will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.3.0] - 2026-08-31
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`refresh-anchor` ledger op**: post-promotion reinforcement now reaches rendered output. When the Learning agent reinforces an already-anchored observation (sharpening its `pattern`/`details`), calling `refresh-anchor <anchor_id>` re-projects the updated log row through the same `toLedgerRow` projector as `assign-anchor` and re-renders all three `.md` files. Previously, post-promotion sharpening was written to the log but never projected forward, so the rendered entry silently froze at its first-promotion snapshot.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **`decisions-ledger.jsonl` is now the anchor registry only (ADR-022)**: `decisions-log.jsonl` is the content authority; the ledger holds anchor numbers and `decisions_status` only. Entry content reaches the ledger exclusively through `assign-anchor` (first promotion) and `refresh-anchor` (post-promotion re-projection) via `toLedgerRow`. The Learning agent's previously sanctioned path of editing ledger rows directly is removed — content changes go to the log, then `refresh-anchor` re-projects. Tooling that reads or writes `decisions-ledger.jsonl` directly is affected.
|
|
15
|
+
- **`/resolve` DUPLICATE verdict**: `/resolve` now collapses duplicate cross-reviewer findings via a new `DUPLICATE` triage verdict — resolution-summary counts unique issues, with a `Duplicates Collapsed` statistics row and a `## Duplicates` section for traceability.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Semicolon-safe `details` field parsing**: the decisions formatter now splits `details` into fields using a segment-aware parser (`segmentDetails`) instead of delimiter regexes. The parser recognises a segment as a new field only when it starts with a known key name followed by `:` (anchored to segment start); semicolons inside values are preserved. Fixes four related defects: truncation at the first internal semicolon, unanchored-key false match (e.g. `reissue:` matching `issue:`), first-match-wins hijack (a key name mentioned inside an earlier value would capture the wrong segment), and newline breakage. Measured blast radius on this repo's own ledger: 111 truncated field extractions before the fix, 0 after. **Installed projects' rendered decisions/pitfalls `.md` may show one-time `--check` drift under the new parser — self-heals on the next ledger op.**
|
|
19
|
+
- **Armed double-assign guard**: `assign-anchor` now writes `anchor_id` back to the log row on promotion, enabling the guard that prevents re-anchoring an already-anchored observation. Previously `anchor_id` was never written back, so the guard was permanently inert and running `assign-anchor` twice on the same observation silently minted two anchors.
|
|
20
|
+
- **Pitfall date stamping and render date-purity**: `assign-anchor` now stamps a `date` field on all entry types (decisions and pitfalls). Previously only decision rows received a date stamp, leaving the 7-day protection window permanently inert for all pitfall entries. Render formatters now use `row.date || ''` (D5) instead of reading the clock, making renders deterministic and avoiding phantom date changes on re-render.
|
|
21
|
+
- **Amendments rendering**: `formatAmendmentsLine` renders the `amendments` field as a `- **Amendments**: ...` line in the entry body. Previously the projected `amendments` field was never rendered, so amendment notes were lost at the `.md` level. Index extraction regexes are now line-anchored (`/m` flag) to prevent amendment text that mentions `- **Status**:` or `- **Area**:` from hijacking the extracted values.
|
|
22
|
+
- **Working memory worker staged-write CAS** (closes #306): the background memory worker now writes to `WORKING-MEMORY.md.new` (staged file, never the real path) and compare-and-swaps into place only if `WORKING-MEMORY.md` is byte-identical to the pre-run snapshot. Previously the success check accepted any mtime bump on a file whose line 1 carried the stamp prefix — including a human's own concurrent edit — and on that false success the worker deleted the unprocessed queue batch and touched `.last-refresh-ok`, producing silent loss of captured turns under a healthy freshness marker.
|
|
23
|
+
- **Stamped pre-compact bootstrap**: `pre-compact-memory` now writes a HEAD SHA stamp on line 1 of `WORKING-MEMORY.md` (guarded by a 40-hex validation gate) and lays out the five canonical sections in fixed order. Previously the bootstrap ran without a stamp, producing "synced @ unknown" at the next SessionStart and an incorrect State-A classification that hid any real drift.
|
|
24
|
+
- **Reconciliation-aware worker prompt**: the memory worker prompt now includes bounded git evidence since the last stamp, explicit reconciliation and expiry guidance, and a strict DONE definition (per PF-010). Addresses unbounded carry-forward, conversation-coined labels promoted to durable state, and no-expiry instruction.
|
|
25
|
+
- **State-C orphaned `.processing` visibility**: `session-start-memory`'s State C queue-depth count now includes lines from any orphaned `.pending-turns.processing` file, not just `.pending-turns.jsonl`. Previously an orphaned `.processing` was invisible to the State C detector, so a CONFLICT-requeued batch did not show in the refresh-failing banner.
|
|
26
|
+
- **`/resolve` base branch token**: resolution summaries now render the base branch name instead of a literal `{base}` token. Step 0b was not extracting `base_branch` while the summary template referenced it.
|
|
27
|
+
- **render summary byte counts**: `render-decisions.cjs` now reports file sizes via `Buffer.byteLength()` instead of `String.length`. The em dash separator in index Area fields (U+2014, 3 UTF-8 bytes, 1 JS character) caused the logged index.md size to be 2 bytes per em dash in the rendered index under the old code.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [2.2.0] - 2026-08-25
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- **Orchestrator charter — self-contained delegation**: added an operating rule requiring every subagent delegation to be self-contained (goal, constraints, relevant session facts, exact paths). Deliverables that draw on the conversation (issues, PRs, reports) must carry the substance in the prompt rather than a pointer to it. Charter grows from 2177 → 2452 bytes (~600 tokens), well within the 4096-byte runtime limit.
|
|
35
|
+
- **Skim agent**: one-view-per-file discipline (pseudo/Read tiers), branch-scoped heatmap (`--diff`, `--window`, `--top`), PATH-first `skim` invocation with `npx rskim` fallback, prose/config skim note
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
8
39
|
## [2.1.0] - 2026-08-25
|
|
9
40
|
|
|
10
41
|
### Added
|
|
@@ -1184,6 +1215,8 @@ devflow init
|
|
|
1184
1215
|
---
|
|
1185
1216
|
|
|
1186
1217
|
[Unreleased]: https://github.com/dean0x/devflow/compare/v2.0.0...HEAD
|
|
1218
|
+
[2.3.0]: https://github.com/dean0x/devflow/compare/v2.2.0...v2.3.0
|
|
1219
|
+
[2.2.0]: https://github.com/dean0x/devflow/compare/v2.1.0...v2.2.0
|
|
1187
1220
|
[2.1.0]: https://github.com/dean0x/devflow/compare/v2.0.1...v2.1.0
|
|
1188
1221
|
[2.0.1]: https://github.com/dean0x/devflow/compare/v2.0.0...v2.0.1
|
|
1189
1222
|
[2.0.0]: https://github.com/dean0x/devflow/compare/v1.8.3...v2.0.0
|
package/dist/commands/resolve.md
CHANGED
|
@@ -50,7 +50,7 @@ In multi-worktree mode, spawn all pre-flight agents **in a single message** (par
|
|
|
50
50
|
|
|
51
51
|
**If BLOCKED:** In single-worktree mode, stop and report the blocker to user. If no reviews found, suggest `/code-review` or `/bug-analysis` first. In multi-worktree mode, report the failure but continue with other worktrees.
|
|
52
52
|
|
|
53
|
-
**Extract from response:** `branch`, `branch_slug`, `pr_number`, `review_count`, `diff_files` per worktree.
|
|
53
|
+
**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number`, `review_count`, `diff_files` per worktree.
|
|
54
54
|
|
|
55
55
|
**Fetch PR body** (after extracting `pr_number`):
|
|
56
56
|
```bash
|
|
@@ -186,7 +186,7 @@ Issues are extracted from `{TARGET_DIR}` only — never cross-reference reviews
|
|
|
186
186
|
### Phase 1b: Fetch External Review Threads (Compliance-gated)
|
|
187
187
|
|
|
188
188
|
**Produces:** THREAD_MAP
|
|
189
|
-
**Requires:**
|
|
189
|
+
**Requires:** BRANCH_INFO, COMPLIANCE_SKILL_INSTALLED
|
|
190
190
|
|
|
191
191
|
Skip this phase if `COMPLIANCE_SKILL_INSTALLED` is false.
|
|
192
192
|
|
|
@@ -205,7 +205,7 @@ Parse `THREAD_MAP` from Git agent output. If Git agent returns `TRACEABILITY: DE
|
|
|
205
205
|
### Phase 2: Global Triage
|
|
206
206
|
|
|
207
207
|
**Produces:** TRIAGE_RESULTS
|
|
208
|
-
**Requires:** ISSUES, DIFF_FILES, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION
|
|
208
|
+
**Requires:** ISSUES, DIFF_FILES, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION
|
|
209
209
|
|
|
210
210
|
Spawn a single global Triage agent for ALL issues:
|
|
211
211
|
|
|
@@ -217,7 +217,7 @@ WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
|
217
217
|
DECISIONS_CONTEXT: {decisions_context}
|
|
218
218
|
FEATURE_KNOWLEDGE: {feature_knowledge}
|
|
219
219
|
PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
|
|
220
|
-
Triage every issue
|
|
220
|
+
Triage every issue: collapse duplicates first, then apply the blast-radius disposition matrix to each group's primary. Assign exactly one verdict per issue.
|
|
221
221
|
Follow devflow:apply-decisions to Read full ADR/PF bodies on demand.
|
|
222
222
|
Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE."
|
|
223
223
|
```
|
|
@@ -229,11 +229,12 @@ Wait for Triage agent to complete before proceeding. Parse verdict ledger from T
|
|
|
229
229
|
- **BY_DESIGN**: Intentional code (with ADR or code doc citation)
|
|
230
230
|
- **FIX_SEPARATE**: Valid but out of blast-radius scope (must become manage-debt ticket)
|
|
231
231
|
- **TECH_DEBT**: Architectural overhaul only — LAST RESORT
|
|
232
|
+
- **DUPLICATE**: Collapsed duplicate issue — carries `duplicate_of: <primary-id>` referencing the non-DUPLICATE primary; inherits the primary's outcome
|
|
232
233
|
|
|
233
234
|
Collect all decisions citations (ADR-NNN / PF-NNN) from Triage agent Reasoning columns.
|
|
234
235
|
|
|
235
236
|
**Triage agent completeness assertion (avoids PF-002):** Verify the parsed ledger against ISSUES before proceeding:
|
|
236
|
-
1. Every issue `id` from ISSUES must appear in exactly one verdict bucket — none may vanish, none may appear in multiple buckets.
|
|
237
|
+
1. Every issue `id` from ISSUES must appear in exactly one verdict bucket — none may vanish, none may appear in multiple buckets. DUPLICATE is a valid bucket; a valid DUPLICATE entry must name its `duplicate_of` primary (the `Duplicate Of` column of the ledger's DUPLICATE table) and that primary must be a non-DUPLICATE issue id. A missing `duplicate_of` or one that chains to another DUPLICATE is a **Triage agent failure** (retry-then-abort as below).
|
|
237
238
|
2. If the Triage agent output is empty, contains a skill re-entrancy guard string (e.g., contains `already running`), or is missing any issue IDs from ISSUES: treat as a **Triage agent failure**:
|
|
238
239
|
- Retry the Triage agent once with the same inputs.
|
|
239
240
|
- If the retry also fails the completeness check: abort with a clear error message listing the missing issue IDs and failure reason — never proceed with dropped issues.
|
|
@@ -247,7 +248,7 @@ Collect all decisions citations (ADR-NNN / PF-NNN) from Triage agent Reasoning c
|
|
|
247
248
|
|
|
248
249
|
If FIX_NOW list is empty: skip to Phase 5 — write full summary (Phase 5), run manage-debt (Phase 9) if FIX_SEPARATE/TECH_DEBT exist, run thread resolution + resolution comment (Phase 9b), run merge readiness (Phase 9c), display results (Phase 10).
|
|
249
250
|
|
|
250
|
-
Otherwise, batch FIX_NOW issues for Code agent execution:
|
|
251
|
+
Otherwise, batch FIX_NOW issues for Code agent execution. **DUPLICATE issues are never dispatched** — they inherit the primary's outcome:
|
|
251
252
|
- **Same-file issues** → one batch (one Code agent per file, sequential for same-file pairs)
|
|
252
253
|
- **Distinct-file issues** → parallel Code agents
|
|
253
254
|
- **Max 5 issues per batch** — chunk large sets
|
|
@@ -255,7 +256,7 @@ Otherwise, batch FIX_NOW issues for Code agent execution:
|
|
|
255
256
|
### Phase 4: Fix (Code agent × N)
|
|
256
257
|
|
|
257
258
|
**Produces:** CODE_AGENT_RESULTS
|
|
258
|
-
**Requires:** BATCHES, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
259
|
+
**Requires:** BATCHES, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
259
260
|
|
|
260
261
|
For each batch, spawn Code agent with `OPERATION: issue-fix` and `PUSH: false`:
|
|
261
262
|
|
|
@@ -284,12 +285,14 @@ Collect from each Code agent:
|
|
|
284
285
|
### Phase 5: Write resolution-summary.md
|
|
285
286
|
|
|
286
287
|
**Produces:** RESOLUTION_FILE (early write for compaction safety)
|
|
287
|
-
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS
|
|
288
|
+
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, BRANCH_INFO
|
|
288
289
|
|
|
289
290
|
**Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool. Do this now — not in Phase 9 — while results are fresh in context. This ensures the record is persisted even if later phases (Simplify, Verification Gate, CI gate, Tech Debt) trigger context compaction.
|
|
290
291
|
|
|
291
292
|
Set `Tracked` for FIX_SEPARATE and TECH_DEBT items to `(pending)` — to be backfilled after Phase 9 manage-debt.
|
|
292
293
|
|
|
294
|
+
DUPLICATE issues are listed **only** in `## Duplicates` — never in `## Fixed Issues`, `## False Positives`, `## By Design`, `## Fix Separately`, `## Deferred to Tech Debt`, `## Escalations`, or `## Blocked`. A duplicate of a FALSE_POSITIVE primary therefore leaves only the primary in the `False Positive` row and the `## False Positives` section; the same holds for every other outcome the duplicate inherits.
|
|
295
|
+
|
|
293
296
|
Use the template from the Output Artifact section below.
|
|
294
297
|
|
|
295
298
|
### Phase 6: Simplify
|
|
@@ -382,7 +385,7 @@ Otherwise, for each worktree with fixes:
|
|
|
382
385
|
|
|
383
386
|
**IMPORTANT**: Run sequentially across all worktrees (not in parallel) to avoid GitHub API conflicts.
|
|
384
387
|
|
|
385
|
-
If any issues are FIX_SEPARATE or TECH_DEBT, spawn Git agent:
|
|
388
|
+
If any issues are FIX_SEPARATE or TECH_DEBT, spawn Git agent. **DUPLICATE issues never create their own debt tickets** — a duplicate of a deferred primary is covered by the primary's ticket:
|
|
386
389
|
|
|
387
390
|
```
|
|
388
391
|
Agent(subagent_type="Git"):
|
|
@@ -407,6 +410,7 @@ Skip this step if `COMPLIANCE_SKILL_INSTALLED` is false or THREAD_MAP is empty.
|
|
|
407
410
|
|
|
408
411
|
Prepare THREAD_MAP with verdicts from triage/code agent results:
|
|
409
412
|
- For each `ext-{N}`: match to an issue verdict (FIXED, FALSE_POSITIVE, BY_DESIGN, ESCALATED) by `file:line` correlation
|
|
413
|
+
- If the matched issue has verdict DUPLICATE, use the **primary's** verdict and verification status for the reply — do not expose DUPLICATE to the thread author (avoids PF-024; caller-side mapping — git.md contracts unchanged)
|
|
410
414
|
- Include `commit_sha` from Code agent results for FIXED verdicts
|
|
411
415
|
- Unmatched threads: ESCALATED (human review)
|
|
412
416
|
|
|
@@ -447,7 +451,7 @@ Update `## Third-Party Threads` section in resolution-summary.md with thread res
|
|
|
447
451
|
### Phase 9c: Merge Readiness (Compliance-gated, Report-only)
|
|
448
452
|
|
|
449
453
|
**Produces:** MERGE_READINESS_REPORT
|
|
450
|
-
**Requires:**
|
|
454
|
+
**Requires:** BRANCH_INFO, COMPLIANCE_SKILL_INSTALLED
|
|
451
455
|
|
|
452
456
|
Skip this phase if `COMPLIANCE_SKILL_INSTALLED` is false.
|
|
453
457
|
|
|
@@ -466,7 +470,7 @@ If Git agent returns `TRACEABILITY: DEGRADED`: warn, proceed to Phase 10.
|
|
|
466
470
|
|
|
467
471
|
### Phase 10: Report
|
|
468
472
|
|
|
469
|
-
**Requires:** TARGET_DIR
|
|
473
|
+
**Requires:** BRANCH_INFO, TARGET_DIR
|
|
470
474
|
|
|
471
475
|
The resolution summary was already written to `{TARGET_DIR}/resolution-summary.md` in Phase 5 (updated by Phase 7 and Phase 9). Display results to the user:
|
|
472
476
|
|
|
@@ -486,6 +490,7 @@ The resolution summary was already written to `{TARGET_DIR}/resolution-summary.m
|
|
|
486
490
|
| Deferred | {n} |
|
|
487
491
|
| Blocked | {n} |
|
|
488
492
|
| Escalated | {n} |
|
|
493
|
+
| Duplicates Collapsed | {n} |
|
|
489
494
|
|
|
490
495
|
### Verification
|
|
491
496
|
Final gate: {PASS | FAILED after N attempts}
|
|
@@ -578,9 +583,9 @@ After writing, commit the two files to the current worktree branch yourself by r
|
|
|
578
583
|
│ └─ Git agent (fetch-review-threads) → THREAD_MAP
|
|
579
584
|
│
|
|
580
585
|
├─ Phase 2: Global Triage [Triage agent, opus, single agent]
|
|
581
|
-
│ └─ ALL issues → verdict ledger by disposition
|
|
586
|
+
│ └─ ALL issues → verdict ledger by disposition (incl. DUPLICATE with duplicate_of)
|
|
582
587
|
│
|
|
583
|
-
├─ Phase 3: Batch FIX_NOW issues (skip if empty)
|
|
588
|
+
├─ Phase 3: Batch FIX_NOW issues (skip if empty; DUPLICATE issues never dispatched)
|
|
584
589
|
│ └─ same-file sequential, distinct-file parallel, max 5/batch
|
|
585
590
|
│
|
|
586
591
|
├─ Phase 4: Fix [Code agent × N, OPERATION: issue-fix, PUSH: false]
|
|
@@ -623,6 +628,8 @@ After writing, commit the two files to the current worktree branch yourself by r
|
|
|
623
628
|
| Worktree pre-flight fails | Report failure, continue with other worktrees |
|
|
624
629
|
| Empty FIX_NOW list | Skip Phases 3-4/6-8; still write full summary + run manage-debt if FIX_SEPARATE/TECH_DEBT exist |
|
|
625
630
|
| ESCALATED security issues | Surfaced in ## Escalations + display callout; never routed to manage-debt |
|
|
631
|
+
| DUPLICATE verdict without duplicate_of, or chained to another DUPLICATE | Treated as Triage failure — same retry-then-abort as a vanished id |
|
|
632
|
+
| DUPLICATE issues in THREAD_MAP | Map ext-{N} to primary's verdict/verification status for thread reply |
|
|
626
633
|
| Verification Gate FAILED after 2 attempts | Recorded as FAILED in ## Verification + blocking callout; CI gate skipped; proceed to Phase 9 (manage-debt) then Phase 10 (display) |
|
|
627
634
|
| gh/GitHub absent | manage-debt fails gracefully; Tracked stays "(pending)" + noted — recorded, not dropped |
|
|
628
635
|
| COMPLIANCE_SKILL_INSTALLED false | Phases 1b, 9b-step-1, and 9c are skipped; post-resolution-summary (Phase 9b step 2) still runs if a PR is known |
|
|
@@ -651,7 +658,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
|
|
|
651
658
|
```markdown
|
|
652
659
|
# Resolution Summary
|
|
653
660
|
|
|
654
|
-
**Branch**: {branch} -> {
|
|
661
|
+
**Branch**: {branch} -> {base_branch}
|
|
655
662
|
**Date**: {timestamp}
|
|
656
663
|
**Review**: {TARGET_DIR}
|
|
657
664
|
**Command**: /resolve
|
|
@@ -673,8 +680,9 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
|
|
|
673
680
|
| Deferred | {n} |
|
|
674
681
|
| Blocked | {n} |
|
|
675
682
|
| Escalated | {n} |
|
|
683
|
+
| Duplicates Collapsed | {n} |
|
|
676
684
|
|
|
677
|
-
_(Note: `Deferred` = `## Fix Separately` count + `## Deferred to Tech Debt` count combined — the two sections are distinct by scope, but the Statistics row aggregates both for the convergence parser.)_
|
|
685
|
+
_(Note: `Deferred` = `## Fix Separately` count + `## Deferred to Tech Debt` count combined — the two sections are distinct by scope, but the Statistics row aggregates both for the convergence parser. `Total Issues` counts every triaged issue including collapsed duplicates; every row **between** `Total Issues` and `Duplicates Collapsed` counts UNIQUE (non-DUPLICATE) issues only, so `Total Issues` equals the sum of the rows below it. Excluding duplicates from `Fixed`, `False Positive`, and `Deferred` de-skews the fp\_ratio convergence formula in code-review without any parser change.)_
|
|
678
686
|
|
|
679
687
|
## Verification
|
|
680
688
|
| Command | Result |
|
|
@@ -720,6 +728,11 @@ Final gate: PASS | FAILED after {n} attempts
|
|
|
720
728
|
|-------|-----------|---------|
|
|
721
729
|
| {description} | {file}:{line} | {why} |
|
|
722
730
|
|
|
731
|
+
## Duplicates
|
|
732
|
+
| Issue | Duplicate Of | File:Line |
|
|
733
|
+
|-------|-------------|-----------|
|
|
734
|
+
| {description} | {primary-id} | {file}:{line} |
|
|
735
|
+
|
|
723
736
|
## Third-Party Threads
|
|
724
737
|
| Thread | File:Line | Verdict | Status |
|
|
725
738
|
|--------|-----------|---------|--------|
|
|
@@ -728,4 +741,4 @@ Final gate: PASS | FAILED after {n} attempts
|
|
|
728
741
|
|
|
729
742
|
_(Omit `## Third-Party Threads` if `COMPLIANCE_SKILL_INSTALLED` is false or no external threads were found.)_
|
|
730
743
|
|
|
731
|
-
**Statistics mapping (parser contract)**: the `Deferred` row = FIX_SEPARATE + TECH_DEBT (both deferral dispositions combined); By Design and Escalated are counted separately and excluded from `Deferred`. The `/code-review` convergence parser reads
|
|
744
|
+
**Statistics mapping (parser contract)**: the `Deferred` row = FIX_SEPARATE + TECH_DEBT (both deferral dispositions combined); By Design and Escalated are counted separately and excluded from `Deferred`. The `Duplicates Collapsed` row is additive — the `/code-review` convergence parser reads only `Deferred`, `Fixed`, and `False Positive` rows plus `## Fixed Issues` / `## False Positives` headings — keep those labels byte-stable. All rows that the parser reads count UNIQUE (non-DUPLICATE) issues only, so collapsed duplicates do not inflate fp\_ratio.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devflow-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "A meta-harness for Claude Code — turns a single coding agent into an engineering team: orchestration, parallel review, persistent memory, self-learning, and graph workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@ skills:
|
|
|
18
18
|
You process the pending decisions queue for one project: claim it atomically, detect
|
|
19
19
|
decision/pitfall patterns worth keeping, curate the existing ledger, and delete the claimed
|
|
20
20
|
queue as your final act. You read and edit the data files directly — no script reads,
|
|
21
|
-
validates, or applies anything on your behalf. The only executables you call are the
|
|
21
|
+
validates, or applies anything on your behalf. The only executables you call are the four
|
|
22
22
|
ledger ops below.
|
|
23
23
|
|
|
24
24
|
## Iron Law
|
|
@@ -26,11 +26,12 @@ ledger ops below.
|
|
|
26
26
|
> **assign-anchor OWNS NUMBERING; render OWNS THE .md; NEVER HAND-EDIT decisions.md, pitfalls.md, or index.md**
|
|
27
27
|
>
|
|
28
28
|
> ADR and PF numbers are assigned exclusively by `assign-anchor`. The `.md` files are written
|
|
29
|
-
> exclusively by `render-decisions.cjs` (invoked internally by `assign-anchor`/`retire-anchor`).
|
|
30
|
-
> One `assign-anchor` invocation claims one number and re-renders all three files
|
|
31
|
-
> (decisions.md, pitfalls.md, index.md
|
|
32
|
-
>
|
|
33
|
-
>
|
|
29
|
+
> exclusively by `render-decisions.cjs` (invoked internally by `assign-anchor`/`retire-anchor`/`refresh-anchor`).
|
|
30
|
+
> One `assign-anchor` invocation claims one number and re-renders all three files
|
|
31
|
+
> (decisions.md, pitfalls.md, index.md — each write atomic; the sequence is not transactional:
|
|
32
|
+
> a crash between writes self-heals on the next op). To deprecate, supersede, or retire an entry, call
|
|
33
|
+
> `retire-anchor <anchor_id> <status>` — never edit the `.md` files directly. Every ledger op
|
|
34
|
+
> re-renders all three files internally; there is no separate render step for you to run.
|
|
34
35
|
|
|
35
36
|
## Environment
|
|
36
37
|
|
|
@@ -39,6 +40,7 @@ are relative to it. The ledger ops live at `$HOME/.devflow/scripts/hooks/json-he
|
|
|
39
40
|
|
|
40
41
|
- `assign-anchor <type> <obs_id>` — claims the next ADR/PF number and re-renders all three `.md` files (decisions.md, pitfalls.md, index.md)
|
|
41
42
|
- `retire-anchor <anchor_id> <status>` — flips a ledger row's rendered status and re-renders
|
|
43
|
+
- `refresh-anchor <anchor_id> [<anchor_id>...]` — variadic: re-projects one or more anchored log rows through the same projector as `assign-anchor` in a single lock/parse/render pass; use after reinforcing already-anchored observations (ADR-022)
|
|
42
44
|
- `rotate-observations` — archives `observing` log rows older than 30 days
|
|
43
45
|
|
|
44
46
|
Each op self-locks internally. Call them plainly — never wrap them in a lock of your own,
|
|
@@ -119,6 +121,23 @@ rewrite the whole file:
|
|
|
119
121
|
timestamps are UTC ISO (`date -u +%Y-%m-%dT%H:%M:%SZ`). Estimate `confidence` honestly —
|
|
120
122
|
it is curation metadata only, NOT a gate; do not inflate it.
|
|
121
123
|
|
|
124
|
+
**`details` grammar**: use `Key: value` segments separated by `;`. Recognised keys are per
|
|
125
|
+
type and disjoint — decisions: `context:`, `decision:`, `rationale:`; pitfalls: `area:`,
|
|
126
|
+
`issue:`, `impact:`, `resolution:`. A segment that begins with a key recognised FOR THAT TYPE
|
|
127
|
+
starts a new field; any other segment (including a key from the opposite type) is appended to
|
|
128
|
+
the previous field's value, so semicolons inside a value are preserved. Keep prose out of key
|
|
129
|
+
positions — do not start a value with text that looks like a recognised key for that type. The
|
|
130
|
+
parser has a recovery pass for legacy mid-segment keys.
|
|
131
|
+
|
|
132
|
+
**`amendments` field**: when reinforcing an already-anchored observation with a dated
|
|
133
|
+
correction or ratification that should remain visible as history (rather than silently
|
|
134
|
+
rewriting `details`), APPEND `{ "date": "YYYY-MM-DD", "note": "..." }` to the log row's
|
|
135
|
+
`amendments` array (create the array if absent). The shape is exactly `{date, note}` — the
|
|
136
|
+
schema guard rejects bare strings. Amendments render at the end of the entry body in
|
|
137
|
+
`decisions.md`/`pitfalls.md`; they never appear in `index.md` lines. A follow-up
|
|
138
|
+
`refresh-anchor <anchor_id>` is required to propagate the addition to the rendered files
|
|
139
|
+
(ADR-022).
|
|
140
|
+
|
|
122
141
|
- **Reinforce an existing row** — use the Edit tool to replace that row's single line:
|
|
123
142
|
increment `observations`, union `evidence` (dedupe, cap 10), update `last_seen`, and
|
|
124
143
|
refresh `pattern`/`details`/`confidence` only where the new evidence sharpens them.
|
|
@@ -134,12 +153,32 @@ node "$HOME/.devflow/scripts/hooks/json-helper.cjs" assign-anchor "pitfall" "obs
|
|
|
134
153
|
NEVER hand-edit `decisions.md` or `pitfalls.md`. NEVER invent an ADR-NNN/PF-NNN number
|
|
135
154
|
yourself — `assign-anchor` is the only source of numbering.
|
|
136
155
|
|
|
156
|
+
**After reinforcing already-anchored observations**: once you have updated all target log rows
|
|
157
|
+
(incrementing `observations`, refreshing `pattern`/`details`, updating `last_seen`), collect
|
|
158
|
+
all anchor ids and make ONE variadic call:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
node "$HOME/.devflow/scripts/hooks/json-helper.cjs" refresh-anchor <anchor_id1> [<anchor_id2> ...]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
This re-projects all sharpened log rows in a single lock/parse/render pass, propagating
|
|
165
|
+
improvements to `decisions.md`/`pitfalls.md`/`index.md`. BATCH: do not call once per row — N
|
|
166
|
+
calls pay N full-corpus renders; one variadic call pays one. Refresh calls do not consume
|
|
167
|
+
curation slots; however, at most 10 anchors may be refreshed per run — stop if the cap is
|
|
168
|
+
reached.
|
|
169
|
+
|
|
137
170
|
## Part 2 — Curation
|
|
138
171
|
|
|
139
172
|
Periodic housekeeping of the ledger and rendered `.md` files. Bounds: **≤5 curation changes
|
|
140
173
|
per run**. **7-day protection window** — never touch any entry whose `date` field in the
|
|
141
174
|
ledger (`.devflow/learning/decisions-ledger.jsonl`) is within the past 7 days. The window key
|
|
142
|
-
is the ledger row's `date` field (YYYY-MM-DD), not anything in the `.md` file.
|
|
175
|
+
is the ledger row's `date` field (YYYY-MM-DD), not anything in the `.md` file. If the ledger
|
|
176
|
+
row lacks a `date` field (pitfall rows promoted before date-stamping was added), use the
|
|
177
|
+
observation log row's `last_seen` date for the window. If `last_seen` is also unavailable, the
|
|
178
|
+
entry predates date-stamping and is outside the protection window (no backfill: a fabricated date would be worse than an unprotected entry — ADR-022).
|
|
179
|
+
Example: a pitfall row with no ledger `date` whose log row has `last_seen: "2026-08-27"` → window
|
|
180
|
+
key 2026-08-27 (protected if within 7 days of today); no ledger `date` AND no log `last_seen`
|
|
181
|
+
→ outside the window, eligible for curation.
|
|
143
182
|
|
|
144
183
|
Ground yourself first, all by direct reads:
|
|
145
184
|
- Active entries and counts: `decisions.md` / `pitfalls.md` — what is rendered is what is active.
|
|
@@ -148,6 +187,13 @@ Ground yourself first, all by direct reads:
|
|
|
148
187
|
those files still exist (Glob). An entry whose referenced files are gone is a preferred
|
|
149
188
|
retirement candidate — a signal to prefer, not an automatic retirement.
|
|
150
189
|
|
|
190
|
+
**PF-040 pointer-vs-citation gate**: before acting on a missing-path signal (a file cited in
|
|
191
|
+
`details`/`evidence` no longer exists), determine whether the reference is a live POINTER (a
|
|
192
|
+
file a reader should follow today) or a HISTORICAL CITATION (the file the entry recorded
|
|
193
|
+
deleting, replacing, or retiring). A missing live pointer is drift — repair the reference. A
|
|
194
|
+
missing historical citation is confirmation that the decision was implemented — leave the entry
|
|
195
|
+
intact.
|
|
196
|
+
|
|
151
197
|
**Rotate stale observations first** (before selecting curation candidates):
|
|
152
198
|
|
|
153
199
|
```bash
|
|
@@ -180,10 +226,13 @@ node "$HOME/.devflow/scripts/hooks/json-helper.cjs" retire-anchor <anchor_id> <s
|
|
|
180
226
|
|
|
181
227
|
`retire-anchor` is atomic and idempotent. Call it once per entry.
|
|
182
228
|
|
|
183
|
-
**Citation preservation
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
`
|
|
229
|
+
**Citation preservation** (ADR-022 — log is content authority): if an entry being retired
|
|
230
|
+
has inbound `applies ADR-NNN` citations in other entries' `pattern`/`details`, update those
|
|
231
|
+
other entries to reference the surviving entry — do this by editing their **log rows** in
|
|
232
|
+
`decisions-log.jsonl` (one line at a time), then collecting all updated anchor ids and calling
|
|
233
|
+
ONCE: `node "$HOME/.devflow/scripts/hooks/json-helper.cjs" refresh-anchor <anchor_id1> [<anchor_id2> ...]`
|
|
234
|
+
Batch all ids into the single variadic call — one lock/parse/render pass for the whole set.
|
|
235
|
+
Never edit the ledger directly for content changes; the log is the authority.
|
|
187
236
|
|
|
188
237
|
**Cap enforcement**: stop after 5 changes regardless of remaining candidates.
|
|
189
238
|
|
|
@@ -191,8 +240,9 @@ instead — edit those ledger rows directly (one line at a time), then re-render
|
|
|
191
240
|
|
|
192
241
|
1. Run `rotate-observations` if you have not already this run (Part 2 covers it — never run
|
|
193
242
|
it twice).
|
|
194
|
-
2. Delete the claim file as your FINAL act, strictly after every other write (
|
|
195
|
-
|
|
243
|
+
2. Delete the claim file as your FINAL act, strictly after every other write (`rm -f` is
|
|
244
|
+
denied by devflow's recommended deny-list; `unlink` and a flagless `rm` both pass — use
|
|
245
|
+
`unlink` (PF-003)):
|
|
196
246
|
`unlink .devflow/learning/.pending-turns.processing`
|
|
197
247
|
If deletion is denied, finish normally and note the leftover claim file in your summary —
|
|
198
248
|
the next run's stale-merge recovery folds it in.
|
|
@@ -9,7 +9,7 @@ skills:
|
|
|
9
9
|
|
|
10
10
|
# Skim Agent
|
|
11
11
|
|
|
12
|
-
You are a codebase orientation specialist. You use
|
|
12
|
+
You are a codebase orientation specialist. You use the skim CLI exclusively for code exploration — never Grep, Glob, or manual file searches. Prefer the `skim` binary when on PATH (`command -v skim`); fall back to `npx rskim`. Examples below show `npx rskim` — substitute `skim` when available. Your output gives implementation agents a clear map of relevant files, functions, and integration points.
|
|
13
13
|
|
|
14
14
|
## Input Context
|
|
15
15
|
|
|
@@ -57,13 +57,16 @@ When the task modifies existing code (refactor, bugfix, extension), run:
|
|
|
57
57
|
npx rskim heatmap --insights
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
Scope with `--path <dir>` when targeting a subdirectory
|
|
60
|
+
On a feature branch, prefer `npx rskim heatmap --insights --diff <base-branch>` to scope findings to the files the branch touches. Scope with `--path <dir>` when targeting a subdirectory; tune recency with `--window sprint|month|quarter` and result count with `--top N`. Skip for greenfield or pure-research tasks. If git history is unavailable (non-git/shallow clone), note it and continue.
|
|
61
61
|
|
|
62
62
|
### Step 5: Targeted Detail
|
|
63
63
|
|
|
64
|
-
For the few specific files that need
|
|
64
|
+
For the few specific files that need more than structure, pick exactly one view per file:
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
- Need the logic but not the exact text → `npx rskim <file> --mode pseudo`
|
|
67
|
+
- Need exact content (edit targets, precise behavior) → the **Read tool directly**
|
|
68
|
+
|
|
69
|
+
If you already know a file needs content, go straight to Read — don't skim it first. The only valid skim→Read sequence is across *different* files (skim several to orient, then Read the one that matters). Skimming and then Reading the same file pays for it twice.
|
|
67
70
|
|
|
68
71
|
### Step 6: Project Knowledge
|
|
69
72
|
|
|
@@ -88,6 +91,10 @@ Produce the orientation summary in the output format below.
|
|
|
88
91
|
| `--mode signatures` | API/function signatures only |
|
|
89
92
|
| `--mode types` | Type definitions only — maximum compression |
|
|
90
93
|
| `heatmap --insights` | Threshold-filtered risk findings from git history |
|
|
94
|
+
| `heatmap --diff <BASE>` | Limit findings to files changed vs BASE (three-dot diff) |
|
|
95
|
+
| `heatmap --window <preset>` | Recency window: `sprint`/`month`/`quarter`/`half`/`year`/`all` |
|
|
96
|
+
|
|
97
|
+
skim also handles prose/config files (`.md`, `.json`, `.yaml`, `.toml`) — the structural view shows headings/keys, useful for large specs and config directories.
|
|
91
98
|
|
|
92
99
|
## Output
|
|
93
100
|
|
|
@@ -123,7 +130,7 @@ Produce the orientation summary in the output format below.
|
|
|
123
130
|
## Principles
|
|
124
131
|
|
|
125
132
|
1. **Speed and focus** — Get oriented quickly on what's relevant; task-focused exploration only
|
|
126
|
-
2. **
|
|
133
|
+
2. **One view per file** — structure via skim, logic via `--mode pseudo`, exact content via Read; never pay for the same file twice, and never skim a file you already know you'll Read
|
|
127
134
|
3. **Be decisive** — Make confident recommendations about where to integrate
|
|
128
135
|
4. **Token efficiency** — Use rskim token budgets and stats to show compression ratio
|
|
129
136
|
|
|
@@ -28,10 +28,22 @@ You receive from orchestrator:
|
|
|
28
28
|
|
|
29
29
|
1. **Read context per issue**: For each issue, Read 30 lines around the reported file:line to understand the actual code.
|
|
30
30
|
2. **Apply Decisions**: Scan the DECISIONS_CONTEXT index to identify relevant ADR and PF entries. Read full bodies on demand. Cite `applies ADR-NNN` / `avoids PF-NNN` in your Reasoning column. Skip when DECISIONS_CONTEXT is empty or `(none)`. Use only verbatim IDs from the index — do not fabricate.
|
|
31
|
-
3. **Assign disposition**:
|
|
31
|
+
3. **Assign disposition**: Run the duplicate grouping pre-pass, then apply the blast-radius matrix to each group's primary. Every issue gets exactly one verdict (DUPLICATE included) — none may vanish.
|
|
32
32
|
4. **Document evidence**: FALSE_POSITIVE requires cited grep/file:line. BY_DESIGN requires an ADR or inline comment/doc citation.
|
|
33
33
|
5. **Assign risk tier**: For every FIX_NOW issue, annotate Standard or Careful.
|
|
34
34
|
|
|
35
|
+
## Duplicate Grouping Pre-Pass
|
|
36
|
+
|
|
37
|
+
Run this pre-pass **before** the disposition matrix. It is a relation between issues, not a matrix row.
|
|
38
|
+
|
|
39
|
+
1. **Group by same defect**: cluster issues that share the same root cause — typically the same or adjacent file:line reported by different review foci, or the same logical error in different phrasings.
|
|
40
|
+
2. **Select primary**: from each group, designate as primary the most specific and complete report — but when a group mixes security and non-security findings (a 'security member' is one that would trigger the Security Gate), the security member is always the primary. All other members are non-primary duplicates.
|
|
41
|
+
3. **Security gate applies to the whole group**: if ANY member is a security finding, the group's primary passes through the Security Gate (→ FIX_NOW or ESCALATED only). Never downgrade a group because non-security members outnumber the security finding.
|
|
42
|
+
4. **Non-primary members**: assign verdict **DUPLICATE** with `duplicate_of: <primary-id>`. Never chain — `duplicate_of` must reference a non-DUPLICATE issue. A DUPLICATE inherits its primary's outcome.
|
|
43
|
+
5. **Single-member groups**: if an issue has no duplicates it is its own primary — apply the matrix directly.
|
|
44
|
+
|
|
45
|
+
Apply the disposition matrix to each group's **primary only**.
|
|
46
|
+
|
|
35
47
|
## Blast-Radius Disposition Matrix
|
|
36
48
|
|
|
37
49
|
**First match wins. Apply in the order listed.**
|
|
@@ -117,6 +129,11 @@ Return the verdict ledger grouped by disposition:
|
|
|
117
129
|
|----------|-----------|----------------------|
|
|
118
130
|
| {id} | {file}:{line} | {why requires complete redesign} |
|
|
119
131
|
|
|
132
|
+
### DUPLICATE
|
|
133
|
+
| Issue ID | Duplicate Of | File:Line | Reason |
|
|
134
|
+
|----------|-------------|-----------|--------|
|
|
135
|
+
| {id} | {primary-id} | {file}:{line} | {same defect as {primary-id}, reported by {focus}} |
|
|
136
|
+
|
|
120
137
|
### Summary
|
|
121
138
|
- Total Issues: {n}
|
|
122
139
|
- ESCALATED: {n}
|
|
@@ -125,6 +142,7 @@ Return the verdict ledger grouped by disposition:
|
|
|
125
142
|
- BY_DESIGN: {n}
|
|
126
143
|
- FIX_SEPARATE: {n}
|
|
127
144
|
- TECH_DEBT: {n}
|
|
145
|
+
- DUPLICATE: {n}
|
|
128
146
|
```
|
|
129
147
|
|
|
130
148
|
## Boundaries
|