devflow-kit 3.9.0 → 3.11.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 +142 -0
- package/README.md +1 -1
- package/dist/agents/code.md +6 -6
- package/dist/agents/fix.md +6 -6
- package/dist/agents/harden.md +7 -6
- package/dist/agents/refactor.md +6 -6
- package/dist/cli/commands/ambient.js +10 -2
- package/dist/cli/commands/backup-session.js +131 -0
- package/dist/cli/commands/compliance-prompts.js +9 -4
- package/dist/cli/commands/compliance.js +184 -24
- package/dist/cli/commands/curation.js +23 -10
- package/dist/cli/commands/gate-level-prompts.js +39 -25
- package/dist/cli/commands/gates.js +5 -7
- package/dist/cli/commands/init.js +169 -184
- package/dist/cli/commands/install-report.js +129 -0
- package/dist/cli/commands/legacy-sweep.js +159 -0
- package/dist/cli/commands/proxy.js +6 -1
- package/dist/cli/commands/rules.js +75 -21
- package/dist/cli/commands/skills.js +42 -9
- package/dist/cli/commands/tracker.js +9 -3
- package/dist/cli/commands/uninstall.js +339 -75
- package/dist/commands/bug-analysis.md +69 -120
- package/dist/commands/dynamic-build.md +23 -23
- package/dist/commands/implement.md +46 -32
- package/dist/commands/release.md +1 -1
- package/dist/commands/resolve.md +35 -31
- package/dist/commands/self-review.md +8 -7
- package/dist/compliance-off/agents/git.md +120 -0
- package/dist/compliance-off/agents/triage.md +180 -0
- package/dist/compliance-off/commands/bug-analysis.md +398 -0
- package/dist/compliance-off/commands/code-review.md +520 -0
- package/dist/compliance-off/commands/dynamic-build.md +1251 -0
- package/dist/compliance-off/commands/dynamic-tickets.md +676 -0
- package/dist/compliance-off/commands/implement.md +736 -0
- package/dist/compliance-off/commands/plan.md +671 -0
- package/dist/compliance-off/commands/release.md +309 -0
- package/dist/compliance-off/commands/resolve.md +742 -0
- package/dist/compliance-off/skills/git/references/decision-markers.md +17 -0
- package/dist/compliance-off/skills/git/references/learn-conventions.md +80 -0
- package/dist/compliance-off/skills/git/references/pr/check-ci-status.md +33 -0
- package/dist/compliance-off/skills/git/references/pr/check-merge-readiness.md +49 -0
- package/dist/compliance-off/skills/git/references/pr/fetch-review-threads.md +52 -0
- package/dist/compliance-off/skills/git/references/pr/validate-branch.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/_contract.md +33 -0
- package/dist/compliance-off/skills/git/references/tracker/_mcp.md +153 -0
- package/dist/compliance-off/skills/git/references/tracker/github/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-traceable-issue.md +74 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issue.md +69 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issues-batch.md +65 -0
- package/dist/compliance-off/skills/git/references/tracker/github/gather-release-evidence.md +48 -0
- package/dist/compliance-off/skills/git/references/tracker/github/setup-task.md +77 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/setup-task.md +82 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/setup-task.md +83 -0
- package/dist/compliance-off/skills/git/references/trust-rule.md +7 -0
- package/dist/core/agent-models.js +19 -4
- package/dist/core/assets.js +126 -17
- package/dist/core/compliance-off-files.js +27 -0
- package/dist/core/compliance.js +14 -0
- package/dist/core/curation-variants.js +460 -112
- package/dist/core/flags.js +2 -2
- package/dist/core/fs-atomic.js +5 -1
- package/dist/core/installed-variants.js +63 -0
- package/dist/core/manifest.js +48 -5
- package/dist/core/mds-variants.js +700 -3
- package/dist/core/orphan-sweep.js +29 -2
- package/dist/core/path-set.js +15 -0
- package/dist/core/plugins.js +68 -10
- package/dist/core/reference-sweep.js +42 -25
- package/dist/core/retired-shipped-names.js +278 -0
- package/dist/curation-compliance-off/agents/triage.md +176 -0
- package/dist/curation-compliance-off/commands/bug-analysis.md +349 -0
- package/dist/curation-compliance-off/commands/code-review.md +481 -0
- package/dist/curation-compliance-off/commands/dynamic-build.md +1211 -0
- package/dist/curation-compliance-off/commands/dynamic-tickets.md +634 -0
- package/dist/curation-compliance-off/commands/implement.md +689 -0
- package/dist/curation-compliance-off/commands/plan.md +631 -0
- package/dist/curation-compliance-off/commands/release.md +279 -0
- package/dist/curation-compliance-off/commands/resolve.md +692 -0
- package/dist/curation-off/agents/code.md +6 -6
- package/dist/curation-off/agents/fix.md +6 -6
- package/dist/curation-off/agents/harden.md +7 -6
- package/dist/curation-off/agents/refactor.md +6 -6
- package/dist/curation-off/commands/bug-analysis.md +69 -119
- package/dist/curation-off/commands/dynamic-build.md +23 -23
- package/dist/curation-off/commands/implement.md +46 -32
- package/dist/curation-off/commands/release.md +1 -1
- package/dist/curation-off/commands/resolve.md +35 -31
- package/dist/curation-off/commands/self-review.md +8 -7
- package/dist/skills/git/references/pr/resolve-review-threads.md +1 -1
- package/dist/targets/claude-code/behavior-install.js +23 -9
- package/dist/targets/claude-code/charter-render.js +374 -0
- package/dist/targets/claude-code/compliance-install.js +62 -17
- package/dist/targets/claude-code/compliance-off-files.js +249 -0
- package/dist/targets/claude-code/curation-install.js +632 -117
- package/dist/targets/claude-code/folder-swap.js +142 -0
- package/dist/targets/claude-code/install-backup.js +780 -0
- package/dist/targets/claude-code/installer.js +795 -199
- package/dist/targets/claude-code/language-stamp.js +6 -0
- package/dist/targets/claude-code/legacy-skill-hashes.js +170 -0
- package/dist/targets/claude-code/linked-folder.js +176 -0
- package/dist/targets/claude-code/reference-converge.js +131 -0
- package/dist/targets/claude-code/rules-folder.js +34 -0
- package/dist/targets/claude-code/shipped-set.js +160 -0
- package/dist/targets/claude-code/tracker-install.js +21 -8
- package/dist/targets/claude-code/tracker-servers.js +20 -6
- package/dist/targets/claude-code/workflow-folder-install.js +251 -0
- package/dist/variant-axes.json +109 -0
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +6 -6
- package/src/assets/agents/evaluate.md +1 -1
- package/src/assets/agents/git.mds +32 -0
- package/src/assets/agents/harden.mds +7 -6
- package/src/assets/agents/test.md +21 -12
- package/src/assets/agents/triage.mds +2 -0
- package/src/assets/agents/validate.md +10 -10
- package/src/assets/commands/_partials/_compliance.mds +5 -3
- package/src/assets/commands/_partials/_engine.mds +9 -8
- package/src/assets/commands/_partials/_publication.mds +10 -1
- package/src/assets/commands/bug-analysis.mds +80 -126
- package/src/assets/commands/code-review.mds +43 -0
- package/src/assets/commands/dynamic-build.mds +109 -15
- package/src/assets/commands/dynamic-tickets.mds +13 -0
- package/src/assets/commands/implement.mds +145 -33
- package/src/assets/commands/plan.mds +19 -0
- package/src/assets/commands/release.mds +50 -1
- package/src/assets/commands/resolve.mds +217 -32
- package/src/assets/commands/self-review.mds +8 -7
- package/src/assets/mds/git/_ops.mds +23 -0
- package/src/assets/mds/git/_ops_steps.mds +17 -0
- package/src/assets/mds/git/_pr.mds +1 -1
- package/src/assets/mds/git/_references.mds +6 -0
- package/src/assets/mds/tracker/_common.mds +4 -0
- package/src/assets/mds/tracker/_github.mds +42 -0
- package/src/assets/mds/tracker/_jira.mds +43 -0
- package/src/assets/mds/tracker/_linear.mds +43 -0
- package/src/assets/rules/quality.md +2 -0
- package/src/assets/scripts/ci-wait.cjs +204 -126
- package/src/assets/scripts/hooks/assets/implement-installed +1 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +13 -11
- package/src/assets/scripts/hooks/preamble +18 -8
- package/src/assets/scripts/hooks/session-start-orchestrator +4 -2
- package/src/assets/scripts/pr-evidence.cjs +41 -2
- package/src/assets/scripts/verify-evidence.cjs +408 -56
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +3 -3
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +1 -1
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +6 -2
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +7 -7
- package/src/assets/skills/docs-framework/SKILL.md +5 -2
- package/src/assets/skills/git/SKILL.md +3 -3
- package/src/assets/skills/git/references/github-api.md +2 -139
- package/src/assets/skills/git/references/github-posting.md +158 -0
- package/src/assets/skills/review-methodology/SKILL.md +1 -1
- package/src/assets/skills/review-methodology/references/patterns.md +1 -1
- package/src/assets/skills/review-methodology/references/report-template.md +1 -2
- package/src/assets/skills/testing/SKILL.md +2 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,146 @@ 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
|
+
## [3.11.0] - 2026-10-31
|
|
9
|
+
|
|
10
|
+
### Upgrade notes — Files that devflow moves to a backup folder
|
|
11
|
+
|
|
12
|
+
**What you must do:**
|
|
13
|
+
- Nothing. If `devflow init` moves a file of yours, the output names the file and its new path.
|
|
14
|
+
- To restore a moved file, copy it from the backup folder, `~/.devflow/install-backups/<UTC stamp>-<8 hex>/`, to one of its stable homes. Skills: `~/.devflow/skills/<name>/`. Rules: `~/.devflow/rules/`. Commands and agents: the top-level `commands/` and `agents/` folders of the Claude directory, outside the `devflow/` subfolders. A file that you put back into a devflow folder moves again on the next `devflow init`.
|
|
15
|
+
|
|
16
|
+
**What to know:**
|
|
17
|
+
- The backup is not encrypted. Devflow never prunes it. It stays until you delete it or run a full uninstall.
|
|
18
|
+
- A file of yours with the same name as a shipped file is overwritten without a report.
|
|
19
|
+
- Relative links in a moved folder can break.
|
|
20
|
+
- Concurrent devflow runs are not supported.
|
|
21
|
+
|
|
22
|
+
### Behaviour change
|
|
23
|
+
|
|
24
|
+
- **Devflow now names the retired files that it removes, and it moves bare legacy skill folders instead of deleting them** ([#688](https://github.com/dean0x/devflow/issues/688)).
|
|
25
|
+
- `devflow init` and the toggles print each retired devflow file that they remove. Before, most of these removals printed nothing.
|
|
26
|
+
- A bare legacy skill folder, such as `skills/python` (a name from releases before v2), is now moved whole to the backup folder and named, but only when its `SKILL.md` is a copy that a release of devflow installed. Before, `devflow init` deleted every such folder. A skill of your own with such a name stays where it is. A folder that devflow cannot judge (no `SKILL.md`, or a link) also stays, and the output names it.
|
|
27
|
+
- A full `devflow uninstall` now removes a bare legacy skill folder, such as `skills/python`, only when its `SKILL.md` is a copy that a release of devflow installed. Before, it deleted every folder with such a name, without a backup, so a skill of your own with that name was lost. A skill of your own stays where it is. A folder that devflow cannot judge (no `SKILL.md`, or a link) also stays. The output names each folder that stays, and `--dry-run` lists the same folders. A `devflow:`-prefixed skill folder is removed as before.
|
|
28
|
+
- An interactive `devflow uninstall` where the install backups are the only user content in `~/.devflow` now asks before the full wipe. The prompt lists the backup folder, and a decline keeps the backups.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`devflow init` and the curation, compliance and rules toggles no longer delete files that devflow did not ship** ([#688](https://github.com/dean0x/devflow/issues/688)).
|
|
33
|
+
- A file that you keep in `commands/devflow/`, `agents/devflow/`, `rules/devflow/`, a `skills/devflow:*` folder or its `references/` folders is now moved to `~/.devflow/install-backups/<UTC stamp>-<8 hex>/`, and the output names it. Before, these commands deleted it. This holds for a full install, for a partial install (`--plugin`) and for the three toggles.
|
|
34
|
+
- A file that cannot move stays in place with its folder, and the output names it.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## [3.10.0] - 2026-10-30
|
|
39
|
+
|
|
40
|
+
### Upgrade notes — Shadowed rules and skills
|
|
41
|
+
|
|
42
|
+
**What you must do:**
|
|
43
|
+
- A quality rule that you keep at `~/.devflow/rules/quality.md` replaces the shipped one, so you do not get its two new bullets. Add them to your copy. Or run `devflow rules unshadow quality`, which deletes your copy, and then run `devflow init`.
|
|
44
|
+
- A testing skill that you keep at `~/.devflow/skills/testing/` replaces the shipped one, so you do not get its new Quality Gates item or its cuts. Add the item to your copy. Or run `devflow skills unshadow testing`, which deletes your copy, and then run `devflow init`.
|
|
45
|
+
- A review-methodology or agent-references skill that you keep under `~/.devflow/skills/` replaces the shipped one, so you do not get the new follow-up text of #690. Add it to your copy. Or run `devflow skills unshadow <name>`, which deletes your copy, and then run `devflow init`.
|
|
46
|
+
|
|
47
|
+
**Stale-install window:**
|
|
48
|
+
- Until you run `devflow init`, the installed quality rule, testing, review-methodology and agent-references skills lack the new text.
|
|
49
|
+
|
|
50
|
+
### Behaviour change
|
|
51
|
+
|
|
52
|
+
- **With compliance off, devflow installs no step or reference that posts to GitHub or a tracker** ([#648](https://github.com/dean0x/devflow/issues/648)).
|
|
53
|
+
- With compliance off (the default for new installs and upgrades), devflow installs no step and no reference that posts test-plan evidence, review or resolution summaries, backlog entries, review-thread replies, wave reports, plan artifacts, or release back-links to GitHub or a tracker. Results stay in local files under `.devflow/docs/`.
|
|
54
|
+
- The change covers the `/implement`, `/resolve`, `/code-review`, `/bug-analysis`, `/dynamic-build`, `/dynamic-tickets`, `/plan` and `/release` commands, the Git and Triage agents, and the reference files that the Git agent reads. Each command names its local result files and marks them `(local; not posted)`. The commands still open pull requests, link issues and file tickets.
|
|
55
|
+
- The Git agent reads one reference file for each operation. With compliance off, devflow installs none of the files for the operations that post: the review summary, the resolution summary, the test-plan evidence, the backlog entry, the review-thread reply, the wave report and the two release back-link operations. This holds for the pull-request host and for each tracker. Devflow also installs neither the publication-gate document nor the `/implement` reference for the evidence questions. The other operation files stay.
|
|
56
|
+
- The GitHub posting recipes moved out of the GitHub API reference into a separate reference, `github-posting.md`. The recipes are the pull-request comments, the review, and the replies to review threads. That reference installs only with compliance on. The GitHub API reference keeps the rate-limit, fetch and release text.
|
|
57
|
+
- With compliance off, devflow no longer adds a link comment to an existing issue. It still creates a new issue when the task has none.
|
|
58
|
+
- The evidence publish script refuses to post unless the machine setting has compliance on. It reads only the machine install record. It ignores the devflow directory setting in the environment, and it reads no repository file. When compliance is off, it prints `TRACEABILITY: DEGRADED (compliance off)`. When it cannot read the record, it prints `TRACEABILITY: DEGRADED (compliance state unreadable)`. In both cases it exits with code 2 and makes no GitHub call.
|
|
59
|
+
- Where the repository requires evidence, each command prints one line: `TRACEABILITY: DEGRADED (compliance off on this machine; the repository requires evidence)`.
|
|
60
|
+
- Only the machine switch picks the installed build. A repository `compliance` key keeps the review lens on, locally, and never brings a posting step back.
|
|
61
|
+
- `devflow init`, `devflow curation` and `devflow compliance` use one converge. Every change of the compliance switch converges the installed commands, agents and references at once. The result equals a fresh install with the same switches, apart from stamps. With compliance off, the converge removes the omitted references. When compliance is on again, it puts each one back with the same bytes. If `devflow compliance` turns compliance on but cannot refresh an installed reference, it records the switch as on, names the cause, and exits 1. If `devflow compliance --disable` cannot show that no installed file still posts, it records the switch as off, lists the files that still post, and exits 1. A listed file can be a command, an agent or a reference. It also exits 1, with no success line, when it cannot remove the compliance rule. The command writes the switch under the install manifest lock. If it cannot take the lock, it writes nothing and exits 1.
|
|
62
|
+
- `devflow init` prints a one-time notice that names this effect. `devflow compliance --status` has a new `Posting:` line.
|
|
63
|
+
- The wave block that `/dynamic-build` writes on such a machine lists links only: `Refs` lines, never `Closes`. It admits `KEY-N` references as well as `#N` references. This corrects the earlier links-only rule, which admitted only `#N` references.
|
|
64
|
+
- Run `devflow init` after you update to install the new commands and references.
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
|
|
68
|
+
- **Plan and code review list follow-up work, and file fewer tickets by default** ([#690](https://github.com/dean0x/devflow/issues/690)).
|
|
69
|
+
- At the `standard` and `lean` levels, `/plan` lists a sibling finding on the plan's deferred list, with no proposed ticket title, and files no ticket for it. You file one only if you want it. The `full` level does not change. The rest of the scope rule does not change.
|
|
70
|
+
- The review-methodology skill lists pre-existing problems and does not suggest separate issues for them. Its report template recommends an issue only for data loss, a false pass or a broken install.
|
|
71
|
+
- The plan levels reference is 47 bytes smaller (4,056 to 4,009), and its ceiling falls with it. The review-methodology skill is 24 bytes smaller, and its report template is 26 bytes larger.
|
|
72
|
+
|
|
73
|
+
- **The quality rule and the testing skill target doc drift, duplicated code and vacuous tests** ([#476](https://github.com/dean0x/devflow/issues/476)).
|
|
74
|
+
- The quality rule has two new bullets. When a change alters a name, path or behavior, the agent updates the current tracked docs that state the old fact, and not released changelog entries. It describes a security fix by its effect only. Before it adds new code, the agent finds the existing owner and extends it when the new code shares its job. A trust-boundary or fail-closed check is not a copy.
|
|
75
|
+
- The Quality Gates of the testing skill have a new item: each new assertion would fail, not error, with the change reverted. The RED run counts; else a bad input or a temporary, uncommitted revert of your own edit shows it, never a stash. Three items that repeated other parts of the skill are cut, and a repeated parenthetical is cut from the flaky-pattern item. The skill is 25 bytes smaller, so the Code and Fix preload totals fall by 25 bytes each (Code 25,514 to 25,489, Fix 14,875 to 14,850). The quality rule is not in the preload and loads in every session: it grows by 326 bytes.
|
|
76
|
+
- A guard pins each new line once, with its limits, and pins a byte ceiling for the two bullets.
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- **A partial install no longer writes through a linked devflow folder** ([#648](https://github.com/dean0x/devflow/issues/648)).
|
|
81
|
+
- If a folder that a partial install writes (commands, rules, agents, a skill folder or its references folder) is a link, the install now writes nothing there. It reports the folder, and you replace it with a real folder and run the install again.
|
|
82
|
+
- **A full install no longer changes files outside its own folder when a skill folder is a link** ([#648](https://github.com/dean0x/devflow/issues/648)).
|
|
83
|
+
- If an installed skill folder is a link, a full install now removes the link and leaves the linked folder as it is. It then installs the skill into a real folder and reports the link.
|
|
84
|
+
- **devflow no longer writes through a linked folder inside its own install folders; it refuses or replaces the link and reports it** ([#648](https://github.com/dean0x/devflow/issues/648)).
|
|
85
|
+
- This applies to the install, to `uninstall --plugin` and to every converge, for example `devflow curation`, `devflow compliance` and `devflow behavior`.
|
|
86
|
+
- **The `/implement` self-review (Harden) states that it never reviews a deleted file or the old path of a rename** ([#571](https://github.com/dean0x/devflow/issues/571)).
|
|
87
|
+
- The file list that Harden gets leaves out deleted files and the old path of a rename. The command now says so.
|
|
88
|
+
- When the prompt lists no file, Harden reports `### Status: PASS` with the line `no files reviewed`. An empty list no longer reads as a completed review, because the final report of `/implement` shows the line, at every gate level. When the prompt has no file list at all, Harden finds the branch changes and reviews them, as before.
|
|
89
|
+
- The docs describe the same rule.
|
|
90
|
+
- **The `/implement` command states that alignment-fix commits get no self-review** ([#572](https://github.com/dean0x/devflow/issues/572)).
|
|
91
|
+
- Phase 4 runs before the alignment fix, so Harden does not review the commits of that fix. The command now says that Phase 6 Validate and `/code-review` check them.
|
|
92
|
+
- The docs describe the same rule.
|
|
93
|
+
- **At `lean`, `/implement` runs the lint pack again after a QA fix** ([#535](https://github.com/dean0x/devflow/issues/535)).
|
|
94
|
+
- The re-validation after a QA fix now gets the gate level and the branch base, as Phase 6 does. A pack match that a QA fix adds is now reported, and the re-validation fails on it, as it does on any other failure.
|
|
95
|
+
- At `lean`, the re-validation labels passed-alone files, and its `Lint pack:` line replaces the one from Phase 6. The pack scans the branch a second time, so a run with QA fixes does that work twice.
|
|
96
|
+
- A pack error after a QA fix reads `UNVERIFIED`, never a pass. So does a re-validation that prints no `Lint pack:` line: it never reads clean, and it never drops an `UNVERIFIED` result from the first validation.
|
|
97
|
+
- At `full` and `standard`, the re-validation prompt does not change.
|
|
98
|
+
- **`/implement` re-validation now follows your compliance, review-publication and PR-title settings, and always runs self-review** ([#544](https://github.com/dean0x/devflow/issues/544)).
|
|
99
|
+
- With compliance on, the fix agents in a re-validation get the compliance guidance, as in a full run. With compliance off, re-validation gives them none, as before.
|
|
100
|
+
- Re-validation now follows your review-publication setting, as a full run does.
|
|
101
|
+
- Re-validation now applies your team's PR-title convention, as a full run does.
|
|
102
|
+
- Re-validation always runs the self-review (Harden) step, at every gate level.
|
|
103
|
+
- **The gate-level step of `devflow init` fits an 80-column terminal** ([#658](https://github.com/dean0x/devflow/issues/658)).
|
|
104
|
+
- Each level hint is now one short line, and no line of the step note is longer than 72 characters.
|
|
105
|
+
- The step note names `/resolve` with the other commands that read the level.
|
|
106
|
+
- The full effect of each level stays in `devflow gates` and in the docs.
|
|
107
|
+
- **`/bug-analysis` no longer reports "no findings" when static analysis could not run** ([#649](https://github.com/dean0x/devflow/issues/649)).
|
|
108
|
+
- When no scanner is installed, it says that static analysis did not run. It no longer reports "no findings" for a run that scanned nothing.
|
|
109
|
+
- A scanner that fails, does not finish or exits with an error is named in the report with its exit status, or says that it had none.
|
|
110
|
+
- File names with spaces or other unusual characters reach the scanners whole.
|
|
111
|
+
- Semgrep and Snyk now run one after the other.
|
|
112
|
+
- **`/bug-analysis` keeps its head marker when static analysis did not cover the commits, and a long scanner result no longer hides findings** ([#652](https://github.com/dean0x/devflow/issues/652), [#661](https://github.com/dean0x/devflow/issues/661)).
|
|
113
|
+
- The marker moves only when every tool that was to run completed, or `--no-static` is set. Otherwise the report keeps the marker and names the way out: fix the tool, or run with `--no-static`. The next run then covers the same commits again.
|
|
114
|
+
- The report shows a status for each tool: completed, not installed, not needed (CodeQL only), no supported language (CodeQL, or Snyk when it finds no supported file), or did not complete with the reason. The summary takes this status from the command, not from the text of a file.
|
|
115
|
+
- Each scanner writes its SARIF to a file, and the session reads counts and a table of the top 50 findings. A long result no longer hides a finding or the exit line. Every finding is saved to a table in the run folder.
|
|
116
|
+
- Snyk keeps each result for a changed file. If its filter fails, the report says so and uses the unfiltered result.
|
|
117
|
+
- CodeQL scans one language, chosen from the changed files: JavaScript or TypeScript, Python, or Ruby. With none of them, the report says that CodeQL had no supported language.
|
|
118
|
+
- Each Semgrep, Snyk and CodeQL call has its Bash timeout at the ceiling: 600000 ms, or `BASH_MAX_TIMEOUT_MS` when set. Devflow sets no time limit of its own on a scanner. A call that reaches the Bash limit counts as not complete.
|
|
119
|
+
- **The orchestrator charter names only installed workflows and routes to more agents.**
|
|
120
|
+
- The charter now names only the workflows that you installed, and it names the Fix agent only when it is installed.
|
|
121
|
+
- It routes to the Test, Evaluate, Harden and Synthesize agents. It routes to the Knowledge agent only when you ask for a new knowledge base. It names the `devflow:bug-analysis` workflow.
|
|
122
|
+
- For debug work, it names `devflow:debug` when that workflow is installed. Otherwise it sends the work to Explore, then Code. It never routes to the Debug agent.
|
|
123
|
+
- A plan handoff no longer points to `devflow:implement` when it is not installed. The prompt gets a generic reminder instead.
|
|
124
|
+
- `devflow ambient --enable` now warns when the ambient agents are not installed. It still registers the hooks.
|
|
125
|
+
- `devflow uninstall --plugin` removes the plan-handoff marker when it removes implement. It does this also when the manifest has no record of the install.
|
|
126
|
+
- `devflow uninstall --plugin` also drops a manifest record that holds the old name of the removed plugin.
|
|
127
|
+
- Run `devflow init` after you update to refresh the charter.
|
|
128
|
+
- **The CI wait and the Validate re-runs no longer stop too early** ([#664](https://github.com/dean0x/devflow/issues/664)). The CI wait waits for CI to start until its 570 s limit, not only 90 s, so a repository with no CI now waits 570 s before the wait reports no CI. When a pull request has only external checks and the repository has no workflow file, the wait ends at once. The CI gates of `/implement` and `/resolve` do not wait again after a full 570 s wait that ends with a head mismatch or no workflow check, so one gate waits at most about 3 x 570 s (28.5 minutes), and only when CI keeps running or its status stays unknown for another cause. Validate no longer stops the re-run of a failed test file alone after 120 s.
|
|
129
|
+
- **Validate waits for a long one-file re-run and reads its result** ([#666](https://github.com/dean0x/devflow/issues/666)). When the re-run of one failed test file runs past its Bash timeout, Validate now waits for it to end and reads its result, so the file gets its label from the real result and no test process stays running with nobody to read it. After one such re-run, Validate re-runs no more files, and the other failed files are REAL.
|
|
130
|
+
- **A run that reaches its Bash timeout is waited for and read, and only the last exit line of the output file that the end notice names sets the result** ([#677](https://github.com/dean0x/devflow/issues/677)).
|
|
131
|
+
- The Code, Fix, Refactor, Validate and Test agents no longer report BLOCKED for a build, test or lint run that passes its Bash timeout. The run moves to the background. The agent makes no tool call, not even a read, until the end notice. Then it reads the last `EXIT=` line of the file that the move names, not the capture log, because a read of the wrong file could report a pass. That line alone sets the result: the end notice and the log do not.
|
|
132
|
+
- A run is BLOCKED only when no `EXIT=` line is read, with its duration and log path. A failed run that is read after the wait gets its re-runs like any failed run. A `LINT_PACK:` line that is read after the wait counts like a line read in time.
|
|
133
|
+
- Splitting a long run into parts is optional. The `bash-max-timeout-ms` flag is optional too, and the agents no longer name it.
|
|
134
|
+
- The one-file re-run in Validate is waited for and read in the same way.
|
|
135
|
+
- `/bug-analysis` waits for a scanner call that reaches the Bash limit, with no tool call until the end notice, and then reads the last `exit=` line of the output file that the notice names, never a scanner file. A scanner call with no `exit=` line read still counts as not complete. Semgrep writes its result to `semgrep.part` and renames it to `semgrep.sarif` when its scan ends, so the SARIF file appears only when the scan ends. The warning for a missing scanner no longer names an install command.
|
|
136
|
+
- `/implement` reports and halts when the Validate report has a Status other than PASS or FAIL, or none. This includes a BLOCKED report, in the validation and in the re-validation. `/resolve` records FAILED and ends its validation loop in the same case. Neither reads it as a pass.
|
|
137
|
+
- Accepted cost: devflow stops no run, so a run that never ends holds its agent until you stop it (Esc). Parallel agents in one wave each wait for their own run.
|
|
138
|
+
- **A test or validation run that gives no result never reads as a pass** ([#679](https://github.com/dean0x/devflow/issues/679), [#680](https://github.com/dean0x/devflow/issues/680), [#681](https://github.com/dean0x/devflow/issues/681)).
|
|
139
|
+
- The Test agent can report `BLOCKED`: no blocking scenario failed, and the command of a blocking scenario gave no result (it could not start, or no `EXIT=` line was read). The report lists each such scenario under `### Blockers`, with its cause, its duration and its log path. A scenario that is skipped because a tool is missing never makes the run BLOCKED. When a blocking scenario is skipped and every blocking scenario that ran passed, the Status line stays `PASS` and names each skip, for example `PASS (1 BLOCKING scenario skipped: no browser tools)`, or `PASS (0 of 3 BLOCKING scenarios ran: all skipped, no browser tools)` when none ran. `/implement`, `/resolve` and the acceptance gate of `/dynamic-build` read that line by its first word, `PASS`; the gate returns the verdict `PASS` without the note. Each test-plan line still gets `PASS`, `FAIL` or `SKIP`, and a line is `PASS` only when at least one scenario covers it and every one passed.
|
|
140
|
+
- `/implement` gives the cause and the log path when it stops on a BLOCKED Validate or Test report. It also stops on a Test report with any other Status or none. It starts no fix agent, and it still records the test-plan claims of that Test report.
|
|
141
|
+
- `/resolve` records a BLOCKED validation as `Final gate: FAILED (Validate blocked)`, with a blocking callout, and starts no fix agent. It still pushes, and the later phases still run. The cause and the log path go only to the report that you see, never to the posted summary. A stale test-plan re-check that is BLOCKED records `Test plan: DEGRADED (Test run blocked)`.
|
|
142
|
+
- In `/dynamic-build`, a BLOCKED, missing or unknown Test result in the acceptance gate keeps the ticket from `PASS`: the run reports `UNVERIFIED`, or `PARTIAL` when the review leaves findings. It starts no fix agent and raises no error. In wave mode such a ticket merges as `UNVERIFIED`, never as `PASS`, and the wave table shows `—` in its Test column. This includes a ticket whose Test reply is missing or empty.
|
|
143
|
+
- The build rules of `/dynamic-build` name all five agents that carry the shared rules for running commands: Code, Fix, Refactor, Validate and Test.
|
|
144
|
+
- **`/self-review` stops when its validation does not pass** ([#695](https://github.com/dean0x/devflow/issues/695)). A Validate report with a Status other than PASS or FAIL, or with no Status, stops the command. This includes a BLOCKED report. The command reports the status, or "none", with its cause and, when the report gives one, its log path. It shows no completion summary. Before, it had steps only for PASS and FAIL, so the summary could read as if validation passed.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
8
148
|
## [3.9.0] - 2026-10-22
|
|
9
149
|
|
|
10
150
|
### Upgrade notes — Evaluate by level
|
|
@@ -2228,6 +2368,8 @@ devflow init
|
|
|
2228
2368
|
---
|
|
2229
2369
|
|
|
2230
2370
|
[Unreleased]: https://github.com/dean0x/devflow/compare/v3.8.0...HEAD
|
|
2371
|
+
[3.11.0]: https://github.com/dean0x/devflow/compare/v3.10.0...v3.11.0
|
|
2372
|
+
[3.10.0]: https://github.com/dean0x/devflow/compare/v3.9.0...v3.10.0
|
|
2231
2373
|
[3.9.0]: https://github.com/dean0x/devflow/compare/v3.8.0...v3.9.0
|
|
2232
2374
|
[3.8.0]: https://github.com/dean0x/devflow/compare/v3.7.0...v3.8.0
|
|
2233
2375
|
[3.7.0]: https://github.com/dean0x/devflow/compare/v3.6.0...v3.7.0
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ This is the **orchestrated flow** — you stay in the loop between every step. W
|
|
|
52
52
|
|
|
53
53
|
## What you get
|
|
54
54
|
|
|
55
|
-
**Ambient orchestration.** Your main session becomes the tech lead: a charter injected at session start turns it into an orchestrator that delegates work to specialized agents and keeps judgment mainline, with one bounded inline exception for a single short git, gh or script command. Plan-mode handoffs
|
|
55
|
+
**Ambient orchestration.** Your main session becomes the tech lead: a charter injected at session start turns it into an orchestrator that delegates work to specialized agents and keeps judgment mainline, with one bounded inline exception for a single short git, gh or script command. Plan-mode handoffs run `/implement` when it is installed. Init and forget.
|
|
56
56
|
|
|
57
57
|
**A staffed agent roster.** 20 specialized agents with explicit model assignments — Opus for analysis, Sonnet for execution, Haiku for I/O. Reassign any agent's model with `devflow agents`, including GPT models through external model routing (`devflow proxy`).
|
|
58
58
|
|
package/dist/agents/code.md
CHANGED
|
@@ -126,13 +126,13 @@ When `OPERATION: issue-fix`, you are fixing pre-classified issues assigned FIX_N
|
|
|
126
126
|
|
|
127
127
|
Run builds, typechecks, lints and tests in the foreground, each with an explicit Bash `timeout` above its expected run time. The ceiling is 600000 ms, or `BASH_MAX_TIMEOUT_MS` when set (`echo ${BASH_MAX_TIMEOUT_MS:-600000}`).
|
|
128
128
|
|
|
129
|
-
- Capture, then tail, in one Bash call
|
|
130
|
-
- Never background a
|
|
131
|
-
- Prefer the scoped command for the change
|
|
132
|
-
- A run
|
|
133
|
-
- A run expected to exceed the ceiling
|
|
129
|
+
- Capture, then tail, in one Bash call: `LOG=$(mktemp); echo "LOG=$LOG"; <command> >"$LOG" 2>&1; rc=$?; tail -n 40 "$LOG"; printf '\nEXIT=%s\n' "$rc"`. The last `EXIT=` line is the result; never decide one from a grep count.
|
|
130
|
+
- Never background a build or test, and never poll across turns: no `sleep` or `true` turns, no sentinel-file checks, no Monitor.
|
|
131
|
+
- Prefer the scoped command for the change; for the whole set, one workspace command over per-package loops.
|
|
132
|
+
- A run past its timeout moves to the background: no tool call, even a Read, until its end notice, then Read the last `EXIT=` line of the file the move names, not `$LOG`; it alone sets the label, not the notice. With none read it is BLOCKED: report its duration and log path. Report only after the end notice.
|
|
133
|
+
- A run expected to exceed the ceiling may be split into parts, run in sequence.
|
|
134
134
|
- Never re-run a command when nothing it reads has changed.
|
|
135
|
-
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they
|
|
135
|
+
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they allow directly.
|
|
136
136
|
- The same rules hold inside a dynamic Workflow sub-agent.
|
|
137
137
|
|
|
138
138
|
## Principles
|
package/dist/agents/fix.md
CHANGED
|
@@ -108,13 +108,13 @@ When `OPERATION: ci-fix`, you are fixing the CI checks the ci-status gate report
|
|
|
108
108
|
|
|
109
109
|
Run builds, typechecks, lints and tests in the foreground, each with an explicit Bash `timeout` above its expected run time. The ceiling is 600000 ms, or `BASH_MAX_TIMEOUT_MS` when set (`echo ${BASH_MAX_TIMEOUT_MS:-600000}`).
|
|
110
110
|
|
|
111
|
-
- Capture, then tail, in one Bash call
|
|
112
|
-
- Never background a
|
|
113
|
-
- Prefer the scoped command for the change
|
|
114
|
-
- A run
|
|
115
|
-
- A run expected to exceed the ceiling
|
|
111
|
+
- Capture, then tail, in one Bash call: `LOG=$(mktemp); echo "LOG=$LOG"; <command> >"$LOG" 2>&1; rc=$?; tail -n 40 "$LOG"; printf '\nEXIT=%s\n' "$rc"`. The last `EXIT=` line is the result; never decide one from a grep count.
|
|
112
|
+
- Never background a build or test, and never poll across turns: no `sleep` or `true` turns, no sentinel-file checks, no Monitor.
|
|
113
|
+
- Prefer the scoped command for the change; for the whole set, one workspace command over per-package loops.
|
|
114
|
+
- A run past its timeout moves to the background: no tool call, even a Read, until its end notice, then Read the last `EXIT=` line of the file the move names, not `$LOG`; it alone sets the label, not the notice. With none read it is BLOCKED: report its duration and log path. Report only after the end notice.
|
|
115
|
+
- A run expected to exceed the ceiling may be split into parts, run in sequence.
|
|
116
116
|
- Never re-run a command when nothing it reads has changed.
|
|
117
|
-
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they
|
|
117
|
+
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they allow directly.
|
|
118
118
|
- The same rules hold inside a dynamic Workflow sub-agent.
|
|
119
119
|
|
|
120
120
|
## Principles
|
package/dist/agents/harden.md
CHANGED
|
@@ -33,16 +33,18 @@ disallowedTools:
|
|
|
33
33
|
|
|
34
34
|
# Harden Agent
|
|
35
35
|
|
|
36
|
-
You are a meticulous self-review specialist. You evaluate implementations against the 9-pillar quality framework and fix the issues you find. You run in a fresh context after the Code and Polish agents complete
|
|
36
|
+
You are a meticulous self-review specialist. You evaluate implementations against the 9-pillar quality framework and fix the issues you find. You run in a fresh context after the Code and Polish agents complete.
|
|
37
37
|
|
|
38
38
|
## Input Context
|
|
39
39
|
|
|
40
40
|
You receive from orchestrator:
|
|
41
41
|
- **TASK_DESCRIPTION**: What was implemented
|
|
42
|
-
- **FILES_CHANGED
|
|
42
|
+
- **FILES_CHANGED** (optional): The branch diff's file list, with no deleted file or old rename path
|
|
43
43
|
- **DECISIONS_CONTEXT** (optional): Compact index of active ADR/PF entries for this repository (pre-rendered to `.devflow/curation/index.md` in its main worktree). `(none)` when absent. Use `devflow:apply-decisions` to Read full bodies on demand.
|
|
44
44
|
- **FEATURE_KNOWLEDGE** (optional): Per KB, the Rules bullets and the KB path, with no heading index, for pattern compliance checking. Check implementation against each bullet's anti-pattern, gotcha or invariant; Read a KB section from its path for more. Follow `devflow:apply-feature-knowledge`.
|
|
45
45
|
|
|
46
|
+
**Empty FILES_CHANGED**: If the prompt has a `FILES_CHANGED` line that lists no file, report `### Status: PASS` with the line `no files reviewed`, and review nothing; with no `FILES_CHANGED` line, find the branch changes and review them.
|
|
47
|
+
|
|
46
48
|
**Worktree Support**: If `WORKTREE_PATH` is provided, follow the `devflow:worktree-support` skill for path resolution. If omitted, use cwd.
|
|
47
49
|
|
|
48
50
|
## Apply Decisions
|
|
@@ -72,10 +74,9 @@ Code-scanning runs in the Code agent; do not scan here.
|
|
|
72
74
|
## Principles
|
|
73
75
|
|
|
74
76
|
1. **Fix, don't report** - Self-review means fixing issues, not generating reports
|
|
75
|
-
2. **
|
|
76
|
-
3. **
|
|
77
|
-
4. **
|
|
78
|
-
5. **Honest assessment** - If P0 issue is unfixable, report BLOCKED immediately
|
|
77
|
+
2. **Pillar priority** - P0 issues block, P1 issues should be fixed, P2 covers Documentation only
|
|
78
|
+
3. **Minimal changes** - Fix the issue, don't refactor surrounding code
|
|
79
|
+
4. **Honest assessment** - If P0 issue is unfixable, report BLOCKED immediately
|
|
79
80
|
|
|
80
81
|
## Output
|
|
81
82
|
|
package/dist/agents/refactor.md
CHANGED
|
@@ -75,13 +75,13 @@ When `OPERATION: edit`, you apply a mechanical change: a rename, a move or boile
|
|
|
75
75
|
|
|
76
76
|
Run builds, typechecks, lints and tests in the foreground, each with an explicit Bash `timeout` above its expected run time. The ceiling is 600000 ms, or `BASH_MAX_TIMEOUT_MS` when set (`echo ${BASH_MAX_TIMEOUT_MS:-600000}`).
|
|
77
77
|
|
|
78
|
-
- Capture, then tail, in one Bash call
|
|
79
|
-
- Never background a
|
|
80
|
-
- Prefer the scoped command for the change
|
|
81
|
-
- A run
|
|
82
|
-
- A run expected to exceed the ceiling
|
|
78
|
+
- Capture, then tail, in one Bash call: `LOG=$(mktemp); echo "LOG=$LOG"; <command> >"$LOG" 2>&1; rc=$?; tail -n 40 "$LOG"; printf '\nEXIT=%s\n' "$rc"`. The last `EXIT=` line is the result; never decide one from a grep count.
|
|
79
|
+
- Never background a build or test, and never poll across turns: no `sleep` or `true` turns, no sentinel-file checks, no Monitor.
|
|
80
|
+
- Prefer the scoped command for the change; for the whole set, one workspace command over per-package loops.
|
|
81
|
+
- A run past its timeout moves to the background: no tool call, even a Read, until its end notice, then Read the last `EXIT=` line of the file the move names, not `$LOG`; it alone sets the label, not the notice. With none read it is BLOCKED: report its duration and log path. Report only after the end notice.
|
|
82
|
+
- A run expected to exceed the ceiling may be split into parts, run in sequence.
|
|
83
83
|
- Never re-run a command when nothing it reads has changed.
|
|
84
|
-
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they
|
|
84
|
+
- Never wrap a build or test command in `sh -c`, `bash -c`, `python3 -c` or `node -e`: permission rules deny wrapped commands they allow directly.
|
|
85
85
|
- The same rules hold inside a dynamic Workflow sub-agent.
|
|
86
86
|
|
|
87
87
|
## Principles
|
|
@@ -4,7 +4,7 @@ import * as path from 'path';
|
|
|
4
4
|
import * as p from '@clack/prompts';
|
|
5
5
|
import color from 'picocolors';
|
|
6
6
|
import { getClaudeDirectory, getDevFlowDirectory } from '../../targets/claude-code/claude-paths.js';
|
|
7
|
-
import { syncManifestFeature } from '../../core/manifest.js';
|
|
7
|
+
import { readManifestPlugins, syncManifestFeature } from '../../core/manifest.js';
|
|
8
8
|
import { writeSettingsFileAtomic } from '../../core/fs-atomic.js';
|
|
9
9
|
import { HOOKS_DIR_SUFFIX, endsWithAny, ensureHook, hasHook, removeHooks, runHookCommand, runHookSuffix, } from '../../targets/claude-code/hooks.js';
|
|
10
10
|
const PREAMBLE_HOOK_MARKER = 'preamble';
|
|
@@ -219,6 +219,14 @@ export function createAmbientCommand() {
|
|
|
219
219
|
// exist, so every prompt would fail.
|
|
220
220
|
const devflowDir = getDevFlowDirectory();
|
|
221
221
|
if (options.enable) {
|
|
222
|
+
// The hooks route to the ambient agents and the rendered charter that `devflow init` installs.
|
|
223
|
+
// The manifest is the record of that install. readManifestPlugins is read-only: unlike
|
|
224
|
+
// readManifest it never heals or rewrites the file. The check runs before the already-enabled
|
|
225
|
+
// return so a repeat run still reports it, and it never blocks the registration below.
|
|
226
|
+
const recordedPlugins = await readManifestPlugins(devflowDir);
|
|
227
|
+
if (recordedPlugins === null || !recordedPlugins.includes('devflow-ambient')) {
|
|
228
|
+
p.log.warn('Ambient agents are not installed. Run `devflow init` to install them.');
|
|
229
|
+
}
|
|
222
230
|
const updated = await addAmbientHook(settingsContent, devflowDir);
|
|
223
231
|
if (updated === settingsContent) {
|
|
224
232
|
// Both hooks already present — addAmbientHook purges any legacy rule anyway
|
|
@@ -228,7 +236,7 @@ export function createAmbientCommand() {
|
|
|
228
236
|
await writeSettingsFileAtomic(settingsPath, updated);
|
|
229
237
|
await syncManifestFeature(devflowDir, 'ambient', true);
|
|
230
238
|
p.log.success('Ambient mode enabled — orchestrator hooks registered');
|
|
231
|
-
p.log.info(color.dim('Charter at session start, reminder per prompt, plan handoffs
|
|
239
|
+
p.log.info(color.dim('Charter at session start, reminder per prompt, plan handoffs run devflow:implement when it is installed (git repos only)'));
|
|
232
240
|
}
|
|
233
241
|
if (options.disable) {
|
|
234
242
|
const updated = await removeAmbientHook(settingsContent);
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backup session of one command run: made once, before the command changes anything, and its
|
|
3
|
+
* record printed once when the command ends.
|
|
4
|
+
*
|
|
5
|
+
* `devflow init`, `devflow curation`, `devflow compliance` and `devflow rules` each make one
|
|
6
|
+
* session with {@link openBackupSession} and wrap the steps that may move or remove files in
|
|
7
|
+
* {@link runWithBackupReport}. The wrapper prints the record after the steps return or throw, so a
|
|
8
|
+
* run that moved a file and then failed still names where the file went.
|
|
9
|
+
*/
|
|
10
|
+
import { randomBytes } from 'crypto';
|
|
11
|
+
import * as p from '@clack/prompts';
|
|
12
|
+
import { WORKFLOW_FOLDERS } from '../../core/mds-variants.js';
|
|
13
|
+
import { getPackageRoot } from '../../core/paths.js';
|
|
14
|
+
import { retiredPathSet } from '../../core/retired-shipped-names.js';
|
|
15
|
+
import { createBackupSession } from '../../targets/claude-code/install-backup.js';
|
|
16
|
+
import { loadShippedSet } from '../../targets/claude-code/shipped-set.js';
|
|
17
|
+
import { formatBackupSummary } from './install-report.js';
|
|
18
|
+
/**
|
|
19
|
+
* Log each summary line at the severity it carries — the one dispatch every
|
|
20
|
+
* `SummaryLine[]` renderer shares.
|
|
21
|
+
*
|
|
22
|
+
* Exhaustive over `SummaryLine['level']` rather than an `if/else`: a level added
|
|
23
|
+
* to the interface has to be routed here, at compile time, instead of silently
|
|
24
|
+
* degrading to `info` at every call site.
|
|
25
|
+
*/
|
|
26
|
+
export function logSummaryLines(lines) {
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
switch (line.level) {
|
|
29
|
+
case 'success':
|
|
30
|
+
p.log.success(line.message);
|
|
31
|
+
break;
|
|
32
|
+
case 'info':
|
|
33
|
+
p.log.info(line.message);
|
|
34
|
+
break;
|
|
35
|
+
case 'warn':
|
|
36
|
+
p.log.warn(line.message);
|
|
37
|
+
break;
|
|
38
|
+
default: {
|
|
39
|
+
const _exhaustive = line.level;
|
|
40
|
+
void _exhaustive;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Make the backup session of a command run, before the command changes anything.
|
|
48
|
+
*
|
|
49
|
+
* The shipped set comes from the full registries and the package source, never from what an
|
|
50
|
+
* earlier install left on disk. When it cannot be built the answer is a message and no session:
|
|
51
|
+
* a session with a smaller set would move devflow's own files aside. The caller prints the
|
|
52
|
+
* message, exits non-zero and changes nothing.
|
|
53
|
+
*/
|
|
54
|
+
export async function openBackupSession(options) {
|
|
55
|
+
const loaded = await loadShippedSet({
|
|
56
|
+
devflowDir: options.devflowDir,
|
|
57
|
+
packageRoot: options.packageRoot ?? getPackageRoot(),
|
|
58
|
+
workflowFolders: WORKFLOW_FOLDERS,
|
|
59
|
+
});
|
|
60
|
+
if (!loaded.ok) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
message: `Could not list the files devflow ships, so nothing was changed: ${loaded.reason}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const session = createBackupSession({
|
|
67
|
+
shipped: loaded.shipped,
|
|
68
|
+
retired: retiredPathSet(),
|
|
69
|
+
claudeDir: options.claudeDir,
|
|
70
|
+
devflowDir: options.devflowDir,
|
|
71
|
+
now: () => new Date(),
|
|
72
|
+
bytes: size => randomBytes(size),
|
|
73
|
+
});
|
|
74
|
+
return { ok: true, session };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The session of a command that reports its failures through the exit code: the session, or null
|
|
78
|
+
* after one error line and exit code 1. The caller then returns without a change.
|
|
79
|
+
*/
|
|
80
|
+
export async function openBackupSessionOrFail(options) {
|
|
81
|
+
const opened = await openBackupSession(options);
|
|
82
|
+
if (opened.ok)
|
|
83
|
+
return opened.session;
|
|
84
|
+
p.log.error(opened.message);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Run `fn`, which makes its session part-way through (it calls `begin`), and print the record of
|
|
90
|
+
* that session once: at its own `print` call, or else after `fn` returns or throws and before the
|
|
91
|
+
* caller returns or rethrows. A step that ends the process (`process.exit`) calls `print` first,
|
|
92
|
+
* since nothing after an exit runs. A throw from `fn` passes on unchanged, and a run that never
|
|
93
|
+
* calls `begin` prints nothing.
|
|
94
|
+
*
|
|
95
|
+
* @param emit - Where the lines go. Defaults to the clack log.
|
|
96
|
+
*/
|
|
97
|
+
export async function runWithLateBackupReport(fn, emit = logSummaryLines) {
|
|
98
|
+
let session = null;
|
|
99
|
+
let printed = false;
|
|
100
|
+
const report = {
|
|
101
|
+
begin: (opened) => { session = opened; },
|
|
102
|
+
print: () => {
|
|
103
|
+
if (printed || session === null)
|
|
104
|
+
return;
|
|
105
|
+
printed = true;
|
|
106
|
+
emit(formatBackupSummary(session.snapshot()));
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
try {
|
|
110
|
+
return await fn(report);
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
report.print();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Run `fn` and print the record of `session` once, after `fn` returns or throws and before the
|
|
118
|
+
* caller returns, rethrows or exits. A throw from `fn` passes on unchanged.
|
|
119
|
+
*
|
|
120
|
+
* `fn` receives `printBackups`, which prints the record at once and is a no-op afterwards: a step
|
|
121
|
+
* that ends the process (`process.exit`) calls it first, since nothing after an exit runs.
|
|
122
|
+
*
|
|
123
|
+
* @param emit - Where the lines go. Defaults to the clack log.
|
|
124
|
+
*/
|
|
125
|
+
export function runWithBackupReport(session, fn, emit = logSummaryLines) {
|
|
126
|
+
return runWithLateBackupReport(async (report) => {
|
|
127
|
+
report.begin(session);
|
|
128
|
+
return fn(report.print);
|
|
129
|
+
}, emit);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=backup-session.js.map
|
|
@@ -126,12 +126,17 @@ export async function runComplianceStep(opts) {
|
|
|
126
126
|
'Stamps the compliance rule with active framework labels and installs\n' +
|
|
127
127
|
'framework reference files into the compliance skill. Only the\n' +
|
|
128
128
|
'frameworks you select are included — zero selection = generic controls.\n\n' +
|
|
129
|
+
'Compliance on also installs the steps that post test-plan evidence, review\n' +
|
|
130
|
+
'and resolution summaries, backlog entries, review-thread replies, wave\n' +
|
|
131
|
+
'reports, plan artifacts and release back-links to GitHub or a tracker.\n' +
|
|
132
|
+
'Compliance off installs none of them; results stay in local files under\n' +
|
|
133
|
+
'.devflow/docs/.\n\n' +
|
|
129
134
|
formatFrameworkCatalogue(), 'Compliance');
|
|
130
135
|
const enableOutcome = await prompts.select({
|
|
131
136
|
message: 'Enable compliance?',
|
|
132
137
|
options: [
|
|
133
|
-
{ value: true, label: 'Yes', hint: 'stamps frameworks into the
|
|
134
|
-
{ value: false, label: 'No', hint: 'enable later with devflow compliance --enable' },
|
|
138
|
+
{ value: true, label: 'Yes', hint: 'stamps frameworks into the rule and skill; installs the steps that post to GitHub or a tracker' },
|
|
139
|
+
{ value: false, label: 'No', hint: 'no step that posts is installed; enable later with devflow compliance --enable' },
|
|
135
140
|
],
|
|
136
141
|
initialValue: seed.enabled,
|
|
137
142
|
});
|
|
@@ -145,7 +150,7 @@ export async function runComplianceStep(opts) {
|
|
|
145
150
|
state: { enabled: false, frameworks: [...seed.frameworks] },
|
|
146
151
|
messages: [{
|
|
147
152
|
level: 'info',
|
|
148
|
-
text: 'Compliance: disabled — enable later with devflow compliance --enable',
|
|
153
|
+
text: 'Compliance: disabled — no step that posts is installed; enable later with devflow compliance --enable',
|
|
149
154
|
}],
|
|
150
155
|
};
|
|
151
156
|
}
|
|
@@ -164,7 +169,7 @@ export async function runComplianceStep(opts) {
|
|
|
164
169
|
return {
|
|
165
170
|
kind: 'resolved',
|
|
166
171
|
state: { enabled: true, frameworks },
|
|
167
|
-
messages: [{ level: 'success', text: `Compliance: enabled (${fwLabel})` }],
|
|
172
|
+
messages: [{ level: 'success', text: `Compliance: enabled (${fwLabel}) — the steps that post are installed` }],
|
|
168
173
|
};
|
|
169
174
|
}
|
|
170
175
|
//# sourceMappingURL=compliance-prompts.js.map
|