mandrel 1.61.0 → 1.63.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/.agents/docs/SDLC.md +10 -3
- package/.agents/docs/workflows.md +1 -1
- package/.agents/scripts/check-action-pinning.js +260 -0
- package/.agents/scripts/check-arch-cycles.js +38 -14
- package/.agents/scripts/epic-deliver-prepare.js +149 -104
- package/.agents/scripts/lib/baseline-snapshot.js +245 -141
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +171 -137
- package/.agents/scripts/lib/orchestration/code-review.js +206 -168
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +71 -5
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +16 -2
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +101 -1
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +20 -42
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +12 -32
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +97 -60
- package/.agents/scripts/lib/orchestration/model-attribution.js +73 -45
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +97 -49
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +73 -69
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +109 -79
- package/.agents/scripts/lib/signals/detectors/common.js +107 -0
- package/.agents/scripts/lib/signals/detectors/hotspot.js +12 -18
- package/.agents/scripts/lib/signals/detectors/retry.js +3 -40
- package/.agents/scripts/lib/signals/detectors/rework.js +3 -40
- package/.agents/scripts/lib/story-body/story-body.js +102 -76
- package/.agents/scripts/providers/github/blocked-by-add.js +252 -0
- package/.agents/scripts/single-story-init.js +16 -3
- package/.agents/workflows/audit-architecture.md +9 -0
- package/.agents/workflows/deliver.md +87 -26
- package/.agents/workflows/helpers/deliver-epic.md +12 -5
- package/.agents/workflows/helpers/deliver-stories.md +13 -7
- package/.agents/workflows/plan.md +3 -1
- package/README.md +1 -1
- package/docs/CHANGELOG.md +40 -0
- package/lib/cli/registry.js +1 -1
- package/lib/cli/update.js +114 -8
- package/package.json +1 -1
|
@@ -14,9 +14,14 @@ description: >-
|
|
|
14
14
|
|
|
15
15
|
## Overview
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
This helper is the **Epic delivery path** behind `/deliver` — the router
|
|
18
|
+
delegates to it once per Epic ID, either as the sole route (single-Epic
|
|
19
|
+
input) or as one **Epic segment** of the sequential segment plan `/deliver`
|
|
20
|
+
composes over mixed Epic / standalone-Story input (Epic segments run in
|
|
21
|
+
input order, after the standalone segment; see
|
|
22
|
+
[`deliver.md`](../deliver.md)). Each invocation opens a PR against `main`
|
|
23
|
+
and auto-merges when every signal certifies a clean run; otherwise it falls
|
|
24
|
+
back to the operator-merges-button path.
|
|
20
25
|
|
|
21
26
|
```text
|
|
22
27
|
/deliver <epicId>
|
|
@@ -32,8 +37,10 @@ clean run; otherwise it falls back to the operator-merges-button path.
|
|
|
32
37
|
→ Phase 9 — cleanup (BranchCleaner + Cleaner lifecycle listeners on epic.cleanup.start / epic.merge.armed; fire via lifecycle-emit → epic.merge.armed)
|
|
33
38
|
```
|
|
34
39
|
|
|
35
|
-
The argument is always
|
|
36
|
-
|
|
40
|
+
The argument is always a single Epic ID (`type::epic`) — multi-Epic or
|
|
41
|
+
mixed input is segmented by the `/deliver` router before this helper runs.
|
|
42
|
+
Story IDs go to
|
|
43
|
+
[`helpers/deliver-stories`](deliver-stories.md) (standalone) or the
|
|
37
44
|
[`helpers/epic-deliver-story`](epic-deliver-story.md) helper
|
|
38
45
|
(Epic-attached, invoked by this workflow's fan-out); Tasks are not directly
|
|
39
46
|
executable.
|
|
@@ -11,10 +11,14 @@ description: >-
|
|
|
11
11
|
|
|
12
12
|
## Overview
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
This helper is the **standalone multi-Story delivery path** behind
|
|
15
|
+
`/deliver`. The router delegates to it whenever the supplied IDs include
|
|
16
|
+
standalone Stories — either as the sole route (Story-only input) or as the
|
|
17
|
+
**standalone segment** of a mixed segment plan (run first, before any Epic
|
|
18
|
+
segments; see [`deliver.md`](../deliver.md)). It takes one or more Story
|
|
19
|
+
IDs, builds a dependency-aware wave plan, optionally confirms it with the
|
|
20
|
+
operator, and fans out one Agent call per Story per wave — parallel within
|
|
21
|
+
each wave, serialised across waves.
|
|
18
22
|
|
|
19
23
|
```text
|
|
20
24
|
/deliver 101 102 103
|
|
@@ -33,11 +37,13 @@ confirms it with the operator, and fans out one Agent call per Story per wave
|
|
|
33
37
|
| 1+ standalone Stories (no `Epic: #N` in body) | `/deliver <id> [<id>...]` |
|
|
34
38
|
| Exactly one standalone Story (lighter path) | `/single-story-deliver <id>` |
|
|
35
39
|
| Epic-attached Stories (have `Epic: #N`) | `/deliver <epicId>` |
|
|
40
|
+
| Mixed Epics + standalone Stories | `/deliver <ids...>` — the router composes a sequential segment plan; this helper delivers the standalone segment first |
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
This helper **refuses** Stories that carry an `Epic: #N` reference in
|
|
38
43
|
their body. Those Stories belong to an Epic's dispatch manifest and must flow
|
|
39
|
-
through `/deliver
|
|
40
|
-
Story when you want the leaner one-story path without wave
|
|
44
|
+
through `/deliver <epicId>`. Use `/single-story-deliver` for a single
|
|
45
|
+
Epic-free Story when you want the leaner one-story path without wave
|
|
46
|
+
machinery.
|
|
41
47
|
|
|
42
48
|
> **Concurrency cap.** The cap is resolved **deterministically in code** by
|
|
43
49
|
> `stories-wave-tick.js` (Phase 1a) — the same `resolveConfig` + `getRunners`
|
|
@@ -126,6 +126,8 @@ stubbed docs, or an unready doctor verdict).
|
|
|
126
126
|
|
|
127
127
|
## See also
|
|
128
128
|
|
|
129
|
-
- [`/deliver`](deliver.md) — the unified delivery entry point.
|
|
129
|
+
- [`/deliver`](deliver.md) — the unified delivery entry point. Accepts a
|
|
130
|
+
single Epic, one or more standalone Stories, or any mix of ≥1 Epics and
|
|
131
|
+
standalone Stories — mixed sets compose a sequential segment plan.
|
|
130
132
|
- [`helpers/plan-epic.md`](helpers/plan-epic.md) /
|
|
131
133
|
[`helpers/plan-story.md`](helpers/plan-story.md) — the path helpers.
|
package/README.md
CHANGED
|
@@ -163,7 +163,7 @@ Deeper reference material lives in `docs/` rather than inline here:
|
|
|
163
163
|
- [`.agents/docs/workflows.md`](.agents/docs/workflows.md) — slash-command
|
|
164
164
|
index (auto-generated from the workflow set).
|
|
165
165
|
- [`docs/CHANGELOG.md`](docs/CHANGELOG.md) — release history.
|
|
166
|
-
- [`AGENTS.md`](AGENTS.md) — repository onboarding, the
|
|
166
|
+
- [`AGENTS.md`](AGENTS.md) — repository onboarding, the single-package release
|
|
167
167
|
topology, PAT / npm-token setup, and major-version policy. Releases are
|
|
168
168
|
automated by `release-please`: land Conventional Commits on `main` and it
|
|
169
169
|
opens a combined `chore: release main` PR that squash-merges itself once
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.63.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.62.0...mandrel-v1.63.0) (2026-06-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
* **decompose:** set native GitHub blocked-by dependencies from Story depends_on graph (refs [#4067](https://github.com/dsj1984/mandrel/issues/4067)) ([#4068](https://github.com/dsj1984/mandrel/issues/4068)) ([1799659](https://github.com/dsj1984/mandrel/commit/1799659a84b06555c9caa1193aec59113c943b78))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
* **audit-architecture:** add Impact severity field to Detailed Findings (refs [#4085](https://github.com/dsj1984/mandrel/issues/4085)) ([#4096](https://github.com/dsj1984/mandrel/issues/4096)) ([d72c109](https://github.com/dsj1984/mandrel/commit/d72c109195955eff70d7d926abb36a88e32d3f6e))
|
|
16
|
+
* fix stale architecture.md/README docs and broaden the import-cycle gate scan root ([#4071](https://github.com/dsj1984/mandrel/issues/4071)) ([#4090](https://github.com/dsj1984/mandrel/issues/4090)) ([2e97b45](https://github.com/dsj1984/mandrel/commit/2e97b45f9ed43398dc703dd735394c7483329033))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Performance
|
|
20
|
+
|
|
21
|
+
* **decompose:** parallelize blocked-by edge creation with bounded concurrentMap (refs [#4082](https://github.com/dsj1984/mandrel/issues/4082)) ([#4094](https://github.com/dsj1984/mandrel/issues/4094)) ([a9f38da](https://github.com/dsj1984/mandrel/commit/a9f38da2d44941a164865a6ad291c2da01ee4ed6))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
* `parseProviderFindings` is a CC-30 ternary thicket ([#4074](https://github.com/dsj1984/mandrel/issues/4074)) ([#4089](https://github.com/dsj1984/mandrel/issues/4089)) ([5ed693c](https://github.com/dsj1984/mandrel/commit/5ed693c3325c05a36251b859be5873ab0378031c))
|
|
27
|
+
* extract shared createDriftDetector skeleton for CRAP and MI drift detectors (refs [#4076](https://github.com/dsj1984/mandrel/issues/4076)) ([#4091](https://github.com/dsj1984/mandrel/issues/4091)) ([e8a81a8](https://github.com/dsj1984/mandrel/commit/e8a81a82307a12c3d6e58275d4c4554b07659f4f))
|
|
28
|
+
* **scripts:** reduce CC of CLI orchestration bodies below the must-fix band (refs [#4075](https://github.com/dsj1984/mandrel/issues/4075)) ([#4093](https://github.com/dsj1984/mandrel/issues/4093)) ([53519de](https://github.com/dsj1984/mandrel/commit/53519de7968e59c08479c886ca3713f53f5c039d))
|
|
29
|
+
* **signals:** hoist shared detector validation preamble into common.js (refs [#4077](https://github.com/dsj1984/mandrel/issues/4077)) ([#4092](https://github.com/dsj1984/mandrel/issues/4092)) ([2f6fe7b](https://github.com/dsj1984/mandrel/commit/2f6fe7b103c208fbd3ea4cfedf63d2a7aa412e24))
|
|
30
|
+
* **single-story-init:** inject spawnSync boundary into makeGhRunner (refs [#4073](https://github.com/dsj1984/mandrel/issues/4073)) ([#4087](https://github.com/dsj1984/mandrel/issues/4087)) ([8fae355](https://github.com/dsj1984/mandrel/commit/8fae35568523e3997d8f7e79580c0cc8e0625072))
|
|
31
|
+
* **story-body:** extract per-section sub-parsers from parse() (refs [#4072](https://github.com/dsj1984/mandrel/issues/4072)) ([#4088](https://github.com/dsj1984/mandrel/issues/4088)) ([aa9e472](https://github.com/dsj1984/mandrel/commit/aa9e47204728da0ab4f547927af251fce6a85b69))
|
|
32
|
+
|
|
33
|
+
## [1.62.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.61.0...mandrel-v1.62.0) (2026-06-12)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
* /deliver composes a sequential segment plan over mixed Epic and standalone-Story ID sets (refs [#4062](https://github.com/dsj1984/mandrel/issues/4062)) ([#4063](https://github.com/dsj1984/mandrel/issues/4063)) ([a83d29e](https://github.com/dsj1984/mandrel/commit/a83d29e032b7f6b6846d7988f071d6b6416df2f9))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
* make mandrel update no-op short-circuit drift-aware (refs [#4065](https://github.com/dsj1984/mandrel/issues/4065)) ([#4066](https://github.com/dsj1984/mandrel/issues/4066)) ([693f1cf](https://github.com/dsj1984/mandrel/commit/693f1cf5bf8fd7d29fed910659708ffceb7a54cb))
|
|
44
|
+
|
|
5
45
|
## [1.61.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.60.0...mandrel-v1.61.0) (2026-06-12)
|
|
6
46
|
|
|
7
47
|
|
package/lib/cli/registry.js
CHANGED
|
@@ -483,7 +483,7 @@ function runAgentsMaterialized({ cwd, existsSync, resolvePackage } = {}) {
|
|
|
483
483
|
* }} [opts]
|
|
484
484
|
* @returns {{ ok: boolean, detail: string, remedy?: string }}
|
|
485
485
|
*/
|
|
486
|
-
function runAgentsDrift({ cwd, fsImpl = fs, resolvePackageRoot } = {}) {
|
|
486
|
+
export function runAgentsDrift({ cwd, fsImpl = fs, resolvePackageRoot } = {}) {
|
|
487
487
|
const getCwd = cwd ?? (() => process.cwd());
|
|
488
488
|
const resolveRoot = resolvePackageRoot ?? defaultResolvePackageRoot;
|
|
489
489
|
const projectRoot = getCwd();
|
package/lib/cli/update.js
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
* ## Ordered cycle (happy path)
|
|
13
13
|
*
|
|
14
14
|
* 1. resolve target version (newest published) and the current version
|
|
15
|
-
* 2.
|
|
15
|
+
* 2. drift-aware short-circuit — version check gates on installed version AND
|
|
16
|
+
* materialized `.agents/` state (Story #4065). When already on newest AND
|
|
17
|
+
* no drift: nothing to do (true no-op). When already on newest BUT drift
|
|
18
|
+
* detected: skip npm-update/migrations, run sync + sync-commands to heal.
|
|
16
19
|
* 3. install — bump the dependency (lockfile bump left STAGED).
|
|
17
20
|
* The package manager is auto-detected from the lockfile in the project
|
|
18
21
|
* root: `pnpm-lock.yaml` ⇒ `pnpm add -D …` (with `-w` at a
|
|
@@ -85,6 +88,11 @@
|
|
|
85
88
|
* - `argv` — subcommand args (after `mandrel update`)
|
|
86
89
|
* - `currentVersion` — the installed `mandrel` version string
|
|
87
90
|
* - `resolveTargetVersion`— async, returns the newest published version
|
|
91
|
+
* - `checkDrift` — sync or async, returns `true` when `.agents/`
|
|
92
|
+
* differs from the installed payload. Used by the
|
|
93
|
+
* drift-aware no-op short-circuit (Story #4065).
|
|
94
|
+
* Defaults to `() => !runAgentsDrift().ok`, which
|
|
95
|
+
* reuses the same `agents-drift` doctor signal.
|
|
88
96
|
* - `npmUpdate` — async, performs the dependency bump (no git);
|
|
89
97
|
* receives `(target, { installCmd })`
|
|
90
98
|
* - `spawnPhase` — async, spawns a post-install phase from the new
|
|
@@ -140,7 +148,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
140
148
|
import { detectPackageManagerWithWorkspace } from '../../.agents/scripts/lib/detect-package-manager.js';
|
|
141
149
|
import { runInstallCommand } from '../../.agents/scripts/lib/install-cmd-parser.js';
|
|
142
150
|
import { runMigrations as defaultRunMigrations } from '../migrations/index.js';
|
|
143
|
-
import { registry } from './registry.js';
|
|
151
|
+
import { registry, runAgentsDrift } from './registry.js';
|
|
144
152
|
import { runSync as defaultRunSync } from './sync.js';
|
|
145
153
|
import { isStale } from './version-check.js';
|
|
146
154
|
import { compareVersions } from './version-helpers.js';
|
|
@@ -761,6 +769,7 @@ function parseInstallCmdFlag(argv) {
|
|
|
761
769
|
* currentVersion?: string | (() => string),
|
|
762
770
|
* resolveTargetVersion?: () => (string | Promise<string>),
|
|
763
771
|
* npmUpdate?: (version: string, opts: { installCmd?: string }) => unknown | Promise<unknown>,
|
|
772
|
+
* checkDrift?: () => (boolean | Promise<boolean>),
|
|
764
773
|
* spawnPhase?: (phase: string, args: string[], opts: { binPath: string, cwd: string, write: (s: string) => void, writeErr: (s: string) => void }) => Promise<{ ok: boolean, stdout: string, stderr: string }> | { ok: boolean, stdout: string, stderr: string },
|
|
765
774
|
* runSync?: typeof defaultRunSync,
|
|
766
775
|
* runMigrations?: typeof defaultRunMigrations,
|
|
@@ -773,7 +782,7 @@ function parseInstallCmdFlag(argv) {
|
|
|
773
782
|
* }} [opts]
|
|
774
783
|
* @returns {Promise<{
|
|
775
784
|
* ok: boolean,
|
|
776
|
-
* action: 'updated' | 'dry-run' | 'up-to-date' | 'doctor-failed',
|
|
785
|
+
* action: 'updated' | 'resynced' | 'dry-run' | 'up-to-date' | 'doctor-failed',
|
|
777
786
|
* currentVersion: string,
|
|
778
787
|
* targetVersion: string | null,
|
|
779
788
|
* stepsRun: string[],
|
|
@@ -785,6 +794,7 @@ export async function runUpdate({
|
|
|
785
794
|
currentVersion,
|
|
786
795
|
resolveTargetVersion,
|
|
787
796
|
npmUpdate,
|
|
797
|
+
checkDrift,
|
|
788
798
|
spawnPhase,
|
|
789
799
|
runSync = defaultRunSync,
|
|
790
800
|
runMigrations = defaultRunMigrations,
|
|
@@ -811,16 +821,112 @@ export async function runUpdate({
|
|
|
811
821
|
const target = String(await resolveTargetVersion());
|
|
812
822
|
|
|
813
823
|
// --- No-op short-circuit --------------------------------------------------
|
|
814
|
-
// Already on (or ahead of) the newest version:
|
|
824
|
+
// Already on (or ahead of) the newest version: check whether .agents/ is
|
|
825
|
+
// actually materialized to the installed payload (agents-drift). When drift
|
|
826
|
+
// is present, fall through to a sync-only heal path even though the package
|
|
827
|
+
// version is unchanged. Only emit "Already up to date" when the version is
|
|
828
|
+
// current AND the payload matches (Story #4065).
|
|
815
829
|
if (compareVersions(target, current) <= 0) {
|
|
816
|
-
|
|
830
|
+
// Resolve the drift probe: prefer the injected checkDrift seam (unit-test
|
|
831
|
+
// friendly); fall back to the production runAgentsDrift helper.
|
|
832
|
+
const driftProbe =
|
|
833
|
+
typeof checkDrift === 'function'
|
|
834
|
+
? checkDrift
|
|
835
|
+
: () => !runAgentsDrift().ok;
|
|
836
|
+
const hasDrift = await driftProbe();
|
|
837
|
+
|
|
838
|
+
if (!hasDrift) {
|
|
839
|
+
write(`✅ Already up to date (v${current} is the newest version).\n`);
|
|
840
|
+
return {
|
|
841
|
+
ok: true,
|
|
842
|
+
action: 'up-to-date',
|
|
843
|
+
currentVersion: current,
|
|
844
|
+
targetVersion: target,
|
|
845
|
+
stepsRun: [],
|
|
846
|
+
dryRun,
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Drift detected while version is already current — heal by re-syncing
|
|
851
|
+
// without bumping the package (no npm-update, no migrations needed since
|
|
852
|
+
// the installed version did not change).
|
|
853
|
+
if (dryRun) {
|
|
854
|
+
write(
|
|
855
|
+
`mandrel update — drift detected, sync heal planned (v${current} is already current)\n`,
|
|
856
|
+
);
|
|
857
|
+
write(
|
|
858
|
+
' 1. runSync — re-materialize .agents/ from installed payload\n',
|
|
859
|
+
);
|
|
860
|
+
write(
|
|
861
|
+
' 2. sync-commands — regenerate .claude/commands/ from .agents/workflows/\n',
|
|
862
|
+
);
|
|
863
|
+
write('Dry run: no files written.\n');
|
|
864
|
+
return {
|
|
865
|
+
ok: true,
|
|
866
|
+
action: 'dry-run',
|
|
867
|
+
currentVersion: current,
|
|
868
|
+
targetVersion: target,
|
|
869
|
+
stepsRun: [],
|
|
870
|
+
dryRun: true,
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
write(
|
|
875
|
+
`Healing .agents/ drift (v${current} is already current, but .agents/ is stale)…\n`,
|
|
876
|
+
);
|
|
877
|
+
const stepsRun = [];
|
|
878
|
+
|
|
879
|
+
const useReExec = typeof spawnPhase === 'function';
|
|
880
|
+
|
|
881
|
+
if (useReExec) {
|
|
882
|
+
const projectRoot = cwd();
|
|
883
|
+
const binPath = resolveNewBinPath(projectRoot);
|
|
884
|
+
|
|
885
|
+
const syncResult = await spawnPhase('sync', [], {
|
|
886
|
+
binPath,
|
|
887
|
+
cwd: projectRoot,
|
|
888
|
+
write,
|
|
889
|
+
writeErr,
|
|
890
|
+
});
|
|
891
|
+
if (!syncResult.ok) {
|
|
892
|
+
throw new Error(
|
|
893
|
+
`mandrel update: \`mandrel sync\` from installed binary exited non-zero — ` +
|
|
894
|
+
'the .agents/ materialization may be incomplete. ' +
|
|
895
|
+
'Run `mandrel sync` manually to restore.',
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
stepsRun.push('runSync');
|
|
899
|
+
|
|
900
|
+
const syncCommandsResult = await spawnPhase('sync-commands', [], {
|
|
901
|
+
binPath,
|
|
902
|
+
cwd: projectRoot,
|
|
903
|
+
write,
|
|
904
|
+
writeErr,
|
|
905
|
+
});
|
|
906
|
+
if (!syncCommandsResult.ok) {
|
|
907
|
+
throw new Error(
|
|
908
|
+
`mandrel update: \`mandrel sync-commands\` from installed binary exited non-zero — ` +
|
|
909
|
+
'the .claude/commands/ tree may be out of sync. ' +
|
|
910
|
+
'Run `npm run sync:commands` manually to restore.',
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
stepsRun.push('sync-commands');
|
|
914
|
+
} else {
|
|
915
|
+
// In-process backward-compat path.
|
|
916
|
+
runSync({ argv: [] });
|
|
917
|
+
stepsRun.push('runSync');
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
write(
|
|
921
|
+
`✅ Healed .agents/ drift (v${current}). The materialized payload is now current.\n`,
|
|
922
|
+
);
|
|
817
923
|
return {
|
|
818
924
|
ok: true,
|
|
819
|
-
action: '
|
|
925
|
+
action: 'resynced',
|
|
820
926
|
currentVersion: current,
|
|
821
927
|
targetVersion: target,
|
|
822
|
-
stepsRun
|
|
823
|
-
dryRun,
|
|
928
|
+
stepsRun,
|
|
929
|
+
dryRun: false,
|
|
824
930
|
};
|
|
825
931
|
}
|
|
826
932
|
|
package/package.json
CHANGED