mandrel 2.64.0 → 2.66.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/agents/acceptance-critic.md +8 -7
- package/.agents/agents/auditor.md +20 -20
- package/.agents/agents/plan-critic.md +8 -7
- package/.agents/agents/story-worker.md +7 -7
- package/.agents/audit-checklists/quality.md +3 -0
- package/.agents/docs/agentrc-reference.json +1 -9
- package/.agents/docs/configuration.md +8 -7
- package/.agents/docs/execution-reference.md +27 -5
- package/.agents/instructions.md +10 -12
- package/.agents/rules/ci-remediation.md +3 -3
- package/.agents/rules/gherkin-standards.md +3 -2
- package/.agents/rules/git-conventions-reference.md +12 -3
- package/.agents/rules/git-conventions.md +9 -7
- package/.agents/rules/testing-standards.md +8 -7
- package/.agents/runtime-deps.json +1 -1
- package/.agents/schemas/agentrc.schema.json +6 -13
- package/.agents/schemas/audit-rules.schema.json +1 -1
- package/.agents/schemas/story-deliver-terminal.schema.json +5 -0
- package/.agents/scripts/bootstrap.js +102 -91
- package/.agents/scripts/check-context-budget.js +1 -1
- package/.agents/scripts/lib/ITicketingProvider.js +1 -3
- package/.agents/scripts/lib/audit-suite/findings.js +1 -17
- package/.agents/scripts/lib/audit-suite/frontmatter.js +0 -28
- package/.agents/scripts/lib/audit-suite/index.js +0 -6
- package/.agents/scripts/lib/audit-suite/selector.js +0 -31
- package/.agents/scripts/lib/baselines/duplication-scanner.js +17 -7
- package/.agents/scripts/lib/bootstrap/agents-md-fold.js +156 -0
- package/.agents/scripts/lib/bootstrap/commit-push.js +1 -1
- package/.agents/scripts/lib/bootstrap/manifest.js +2 -2
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +91 -107
- package/.agents/scripts/lib/cli/standard-args.js +60 -76
- package/.agents/scripts/lib/cli-args.js +26 -0
- package/.agents/scripts/lib/config/gates/shared.js +3 -3
- package/.agents/scripts/lib/config/review-chain-default.js +13 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-quality.js +11 -13
- package/.agents/scripts/lib/doc-tiers.js +25 -6
- package/.agents/scripts/lib/feedback-loop/graduate-steps.js +205 -0
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +47 -782
- package/.agents/scripts/lib/feedback-loop/graduator-gh.js +449 -0
- package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
- package/.agents/scripts/lib/observability/close-telemetry.js +330 -0
- package/.agents/scripts/lib/observability/metrics-ledger.js +0 -72
- package/.agents/scripts/lib/observability/runtime-friction.js +2 -0
- package/.agents/scripts/lib/observability/signal-validator.js +17 -5
- package/.agents/scripts/lib/orchestration/code-review.js +33 -6
- package/.agents/scripts/lib/orchestration/epic-rollup.js +29 -12
- package/.agents/scripts/lib/orchestration/merge-block-class.js +20 -4
- package/.agents/scripts/lib/orchestration/merge-poll.js +41 -22
- package/.agents/scripts/lib/orchestration/plan-metrics.js +76 -63
- package/.agents/scripts/lib/orchestration/required-checks.js +147 -0
- package/.agents/scripts/lib/orchestration/review-providers/code-review.js +203 -0
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +29 -4
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +3 -2
- package/.agents/scripts/lib/orchestration/run-epilogue.js +6 -0
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +1 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +2 -12
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +370 -268
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +21 -7
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +112 -82
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +4 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +393 -313
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +12 -87
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +3 -0
- package/.agents/scripts/lib/orchestration/ticket-validator.js +19 -36
- package/.agents/scripts/lib/signals/detectors/common.js +63 -51
- package/.agents/scripts/lib/templates/decomposer-prompts.js +5 -24
- package/.agents/scripts/lib/transpile.js +28 -3
- package/.agents/scripts/providers/github/issues.js +14 -23
- package/.agents/scripts/single-story-close.js +10 -2
- package/.agents/scripts/single-story-confirm-merge.js +267 -238
- package/.agents/scripts/sync-claude-agents.js +1 -1
- package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -2
- package/.agents/workflows/audit-architecture.md +5 -4
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-performance.md +10 -10
- package/.agents/workflows/audit-quality.md +42 -7
- package/.agents/workflows/helpers/acceptance-self-eval.md +9 -9
- package/.agents/workflows/helpers/audit-lens-core.md +30 -57
- package/.agents/workflows/helpers/code-review.md +15 -38
- package/.agents/workflows/helpers/deliver-digest.md +2 -2
- package/.agents/workflows/helpers/deliver-reference.md +7 -3
- package/.agents/workflows/helpers/deliver-story.md +9 -1
- package/.agents/workflows/helpers/parallel-tooling.md +16 -18
- package/.agents/workflows/helpers/plan-reference.md +9 -8
- package/.agents/workflows/mandrel-deliver.md +3 -2
- package/.agents/workflows/mandrel-plan.md +11 -7
- package/.agents/workflows/mandrel-update.md +5 -3
- package/docs/CHANGELOG.md +57 -0
- package/lib/cli/claude-code-version.js +73 -0
- package/lib/cli/doctor.js +2 -2
- package/lib/cli/guarded-sync.js +87 -0
- package/lib/cli/registry.js +9 -0
- package/lib/cli/sync-agents.js +9 -92
- package/lib/cli/sync-commands.js +9 -101
- package/lib/cli/uninstall.js +37 -9
- package/lib/migrations/index.js +2 -0
- package/lib/migrations/steps/2.65.0-fold-claude-md-into-agents-md.js +38 -0
- package/package.json +3 -2
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +0 -99
- package/.agents/scripts/lib/audit-suite/runner.js +0 -205
- package/.agents/scripts/lib/audit-suite/substitutions.js +0 -96
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +0 -37
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +0 -234
package/docs/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,63 @@ All notable changes to this project will be documented in this file.
|
|
|
15
15
|
-->
|
|
16
16
|
<!-- markdownlint-disable-file MD004 MD012 MD037 -->
|
|
17
17
|
|
|
18
|
+
## [2.66.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.65.0...mandrel-v2.66.0) (2026-09-26)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
* record per-Story retry causes and per-provider review halts at close ([#5435](https://github.com/dsj1984/mandrel/issues/5435)) ([#5441](https://github.com/dsj1984/mandrel/issues/5441)) ([c7bfd5a](https://github.com/dsj1984/mandrel/commit/c7bfd5ab2be417889f45a85f92145704ac580b88))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
* make the quality instruments fail loudly instead of silently mis-measuring, and reclaim floor slack ([#5444](https://github.com/dsj1984/mandrel/issues/5444)) ([#5452](https://github.com/dsj1984/mandrel/issues/5452)) ([54eb9fd](https://github.com/dsj1984/mandrel/commit/54eb9fd4660a0476740e0f96daae34e7f1fc754f))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Performance
|
|
32
|
+
|
|
33
|
+
* stop tests and CLI start-up from spending real wall-clock on host state and sleeps ([#5445](https://github.com/dsj1984/mandrel/issues/5445)) ([#5451](https://github.com/dsj1984/mandrel/issues/5451)) ([8f74d51](https://github.com/dsj1984/mandrel/commit/8f74d51da489b3cc96a0c23053338a718a68708c))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
* burn down the bootstrap hotspots across CRAP, cyclomatic and dead exports ([#5447](https://github.com/dsj1984/mandrel/issues/5447)) ([#5455](https://github.com/dsj1984/mandrel/issues/5455)) ([be9e666](https://github.com/dsj1984/mandrel/commit/be9e6665011547be9396670f9a7486951ca1cd81))
|
|
39
|
+
* burn down the orchestration and signals complexity outliers ([#5449](https://github.com/dsj1984/mandrel/issues/5449)) ([#5456](https://github.com/dsj1984/mandrel/issues/5456)) ([208cede](https://github.com/dsj1984/mandrel/commit/208cede77cb8186bf479cb6e190b8e2849347bbf))
|
|
40
|
+
* collapse duplicated CLI plumbing: standard-args flag switches and the sync-agents/sync-commands clone ([#5448](https://github.com/dsj1984/mandrel/issues/5448)) ([#5454](https://github.com/dsj1984/mandrel/issues/5454)) ([5df933b](https://github.com/dsj1984/mandrel/commit/5df933b7c567730eae0ed47b172a8ac670d0831e))
|
|
41
|
+
* decompose the single-story-close and confirm-merge hot path ([#5446](https://github.com/dsj1984/mandrel/issues/5446)) ([#5453](https://github.com/dsj1984/mandrel/issues/5453)) ([3b7a5ae](https://github.com/dsj1984/mandrel/commit/3b7a5ae2b7391e16dddfd18d64e7fe4528bdc48c))
|
|
42
|
+
* trim the always-on closure and document the effort policy ([#5437](https://github.com/dsj1984/mandrel/issues/5437)) ([#5439](https://github.com/dsj1984/mandrel/issues/5439)) ([61d3c66](https://github.com/dsj1984/mandrel/commit/61d3c666637d38144cee7abcc7a50f28c332201a))
|
|
43
|
+
|
|
44
|
+
## [2.65.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.64.0...mandrel-v2.65.0) (2026-09-24)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### ⚠ BREAKING CHANGES
|
|
48
|
+
|
|
49
|
+
* consumers must run Claude Code >= 2.1.277, which loads a root AGENTS.md; `mandrel update` folds the root CLAUDE.md into AGENTS.md and deletes CLAUDE.md.
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
* add a low-effort model bug review to close and pin role-agent effort ([#5426](https://github.com/dsj1984/mandrel/issues/5426)) ([#5431](https://github.com/dsj1984/mandrel/issues/5431)) ([ec39643](https://github.com/dsj1984/mandrel/commit/ec3964390210e140ebaa324bbfe27b67fd470fa4))
|
|
54
|
+
* **audit-quality:** add a property-based coverage dimension (refs [#5425](https://github.com/dsj1984/mandrel/issues/5425)) ([#5428](https://github.com/dsj1984/mandrel/issues/5428)) ([f78fd62](https://github.com/dsj1984/mandrel/commit/f78fd62edda9060580b1cbacaec1cc82875040d1))
|
|
55
|
+
* cut consumers over to AGENTS.md: bootstrap wiring, CLAUDE.md fold migration, uninstall revert, Claude Code version doctor check ([#5410](https://github.com/dsj1984/mandrel/issues/5410)) ([#5411](https://github.com/dsj1984/mandrel/issues/5411)) ([df69d59](https://github.com/dsj1984/mandrel/commit/df69d59e7ced7342f321b8435ab50b317655f7f3))
|
|
56
|
+
* make AGENTS.md mandrel's always-loaded entry doc: host-faithful closure resolver, delete CLAUDE.md, rewrite AGENTS.md ([#5409](https://github.com/dsj1984/mandrel/issues/5409)) ([#5413](https://github.com/dsj1984/mandrel/issues/5413)) ([929e5bb](https://github.com/dsj1984/mandrel/commit/929e5bb6834e1a25152163ac34a87d327034ce05))
|
|
57
|
+
* trim legacy story-author scaffolding and drop two needless workflow stops ([#5427](https://github.com/dsj1984/mandrel/issues/5427)) ([#5429](https://github.com/dsj1984/mandrel/issues/5429)) ([7b39d36](https://github.com/dsj1984/mandrel/commit/7b39d3637b4911ad7122d6cbaef3c19c88704101))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
* merge wait: fail fast on a red required check without waiting for unrelated jobs ([#5415](https://github.com/dsj1984/mandrel/issues/5415)) ([#5420](https://github.com/dsj1984/mandrel/issues/5420)) ([381d8ff](https://github.com/dsj1984/mandrel/commit/381d8ff4145ec3210d984936904368d51cde426a))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Performance
|
|
66
|
+
|
|
67
|
+
* close: per-phase timing, faster merge observation, concurrent post-land GitHub steps ([#5417](https://github.com/dsj1984/mandrel/issues/5417)) ([#5423](https://github.com/dsj1984/mandrel/issues/5423)) ([2d3c537](https://github.com/dsj1984/mandrel/commit/2d3c5373402ad0e212951b70ca2880204da3a8f3))
|
|
68
|
+
* epic rollup: stop reading every Epic's sub-issues when a Story has no native parent ([#5414](https://github.com/dsj1984/mandrel/issues/5414)) ([#5419](https://github.com/dsj1984/mandrel/issues/5419)) ([025c650](https://github.com/dsj1984/mandrel/commit/025c650409a757b47be9847a4584e5e45fdef8e8))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
* retire the Story-scope local-lens pass from close ([#5416](https://github.com/dsj1984/mandrel/issues/5416)) ([#5422](https://github.com/dsj1984/mandrel/issues/5422)) ([ecd86da](https://github.com/dsj1984/mandrel/commit/ecd86daa1a9d1ddff7f58e7f832e491a9c58cb68))
|
|
74
|
+
|
|
18
75
|
## [2.64.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.63.0...mandrel-v2.64.0) (2026-09-19)
|
|
19
76
|
|
|
20
77
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// lib/cli/claude-code-version.js
|
|
2
|
+
/**
|
|
3
|
+
* `mandrel doctor` check `claude-code-version`: an AGENTS.md-only project
|
|
4
|
+
* needs a Claude Code host that loads AGENTS.md at all. Below the floor the
|
|
5
|
+
* framework never hydrates, so the check fails. A missing `claude` binary,
|
|
6
|
+
* unparseable output, or a project still carrying CLAUDE.md skips with
|
|
7
|
+
* `ok: true` so headless/CI hosts are never blocked. The `claude --version`
|
|
8
|
+
* spawn is injected by the registry (fixed argv, never user input); with no
|
|
9
|
+
* runner the check skips.
|
|
10
|
+
*
|
|
11
|
+
* @module cli/claude-code-version
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
|
|
17
|
+
import { compareVersions } from './version-helpers.js';
|
|
18
|
+
|
|
19
|
+
/** Oldest Claude Code release that loads a root AGENTS.md. */
|
|
20
|
+
export const CLAUDE_CODE_AGENTS_MD_FLOOR = '2.1.277';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} text
|
|
24
|
+
* @returns {string|null} the leading `x.y.z`, or null
|
|
25
|
+
*/
|
|
26
|
+
export function parseClaudeVersion(text) {
|
|
27
|
+
const match = /^\s*v?(\d+\.\d+\.\d+)/.exec(text ?? '');
|
|
28
|
+
return match ? match[1] : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {{
|
|
33
|
+
* projectRoot?: string,
|
|
34
|
+
* cwd?: () => string,
|
|
35
|
+
* existsSync?: (p: string) => boolean,
|
|
36
|
+
* runClaude?: () => { status: number|null, stdout: string, error?: NodeJS.ErrnoException },
|
|
37
|
+
* }} [opts]
|
|
38
|
+
* @returns {{ ok: boolean, detail: string, remedy?: string }}
|
|
39
|
+
*/
|
|
40
|
+
export function runClaudeCodeVersion({
|
|
41
|
+
projectRoot,
|
|
42
|
+
cwd = () => process.cwd(),
|
|
43
|
+
existsSync = fs.existsSync,
|
|
44
|
+
runClaude = () => ({ status: null, stdout: '', error: new Error('none') }),
|
|
45
|
+
} = {}) {
|
|
46
|
+
const root = projectRoot ?? cwd();
|
|
47
|
+
if (existsSync(path.join(root, 'CLAUDE.md'))) {
|
|
48
|
+
return { ok: true, detail: 'skipped: CLAUDE.md present' };
|
|
49
|
+
}
|
|
50
|
+
if (!existsSync(path.join(root, 'AGENTS.md'))) {
|
|
51
|
+
return { ok: true, detail: 'skipped: no AGENTS.md' };
|
|
52
|
+
}
|
|
53
|
+
const r = runClaude();
|
|
54
|
+
if (r.error || r.status !== 0) {
|
|
55
|
+
return { ok: true, detail: 'skipped: claude not found on PATH' };
|
|
56
|
+
}
|
|
57
|
+
const version = parseClaudeVersion(r.stdout);
|
|
58
|
+
if (!version) {
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
detail: 'skipped: unparseable `claude --version` output',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const detail = `Claude Code ${version} (required >=${CLAUDE_CODE_AGENTS_MD_FLOOR} to load AGENTS.md)`;
|
|
65
|
+
if (compareVersions(version, CLAUDE_CODE_AGENTS_MD_FLOOR) >= 0) {
|
|
66
|
+
return { ok: true, detail };
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
detail,
|
|
71
|
+
remedy: `Upgrade Claude Code to >=${CLAUDE_CODE_AGENTS_MD_FLOOR} (e.g. \`claude update\`) — older hosts do not load AGENTS.md, so the framework never hydrates.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
package/lib/cli/doctor.js
CHANGED
|
@@ -54,7 +54,7 @@ function formatSummary(passed, total) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
* Informational line for the
|
|
57
|
+
* Informational line for the host entry doc's always-loaded closure (file count,
|
|
58
58
|
* KB). Never counted toward the verdict; a resolve failure degrades to a
|
|
59
59
|
* neutral line.
|
|
60
60
|
*
|
|
@@ -73,7 +73,7 @@ export function formatClosureReport({
|
|
|
73
73
|
return `ℹ ${label} always-loaded closure unavailable\n`;
|
|
74
74
|
}
|
|
75
75
|
if (files.length === 0) {
|
|
76
|
-
return `ℹ ${label} no CLAUDE.md
|
|
76
|
+
return `ℹ ${label} no entry-doc closure found (CLAUDE.md or AGENTS.md)\n`;
|
|
77
77
|
}
|
|
78
78
|
const kb = (tierTotalBytes(files) / 1024).toFixed(1);
|
|
79
79
|
return `ℹ ${label} ${files.length} file(s), ${kb} KB always-loaded\n`;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// lib/cli/guarded-sync.js
|
|
2
|
+
/**
|
|
3
|
+
* Shared body of `mandrel sync-commands` / `mandrel sync-agents`: run a
|
|
4
|
+
* `.agents/scripts/` projector in a child process, forwarding its exit code.
|
|
5
|
+
* Refuses first when `.agents/` does not match the running CLI (version
|
|
6
|
+
* marker, else the `agents-drift` check): `.claude/*` is gitignored, so a
|
|
7
|
+
* stale projection surfaces only when an agent hits a missing module.
|
|
8
|
+
* The marker is read from `cwd()`; `PROJECT_ROOT` only names this CLI's version.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { spawnSync } from 'node:child_process';
|
|
12
|
+
import nodeFs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
|
|
16
|
+
import { runAgentsDrift } from './registry.js';
|
|
17
|
+
import { readVersionMarker } from './sync.js';
|
|
18
|
+
|
|
19
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
// lib/cli/ → lib/ → project root
|
|
21
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
|
22
|
+
|
|
23
|
+
function resolveOwnPackageVersion(fsImpl) {
|
|
24
|
+
const parsed = JSON.parse(
|
|
25
|
+
fsImpl.readFileSync(path.join(PROJECT_ROOT, 'package.json'), 'utf8'),
|
|
26
|
+
);
|
|
27
|
+
return String(parsed.version);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function refusalReason(projectRoot, { fs, ownVersion, checkAgentsDrift, cwd }) {
|
|
31
|
+
const marker = readVersionMarker(projectRoot, fs);
|
|
32
|
+
if (marker) {
|
|
33
|
+
const own = ownVersion ?? resolveOwnPackageVersion(fs);
|
|
34
|
+
if (marker === own) return null;
|
|
35
|
+
return {
|
|
36
|
+
what: `the materialized .agents/ tree is v${marker} but the running CLI is v${own}`,
|
|
37
|
+
fix: 're-materialize .agents/ to the current version',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const drift = (checkAgentsDrift ?? (() => runAgentsDrift({ cwd })))();
|
|
41
|
+
if (drift.ok) return null;
|
|
42
|
+
return {
|
|
43
|
+
what: `.agents/ appears to have drifted from the installed package payload (${drift.detail})`,
|
|
44
|
+
fix: 'restore the materialized .agents/ payload',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {{ command: string, target: string, script: string }} spec
|
|
50
|
+
* @param {string[]} _argv - Unused; reserved for future flags.
|
|
51
|
+
* @param {object} [opts] - Injectable runner, cwd, fs, version and I/O seams.
|
|
52
|
+
*/
|
|
53
|
+
export function runGuardedSync(
|
|
54
|
+
{ command, target, script },
|
|
55
|
+
_argv = [],
|
|
56
|
+
{
|
|
57
|
+
runner = spawnSync,
|
|
58
|
+
cwd = () => process.cwd(),
|
|
59
|
+
fs = nodeFs,
|
|
60
|
+
ownVersion,
|
|
61
|
+
checkAgentsDrift,
|
|
62
|
+
writeErr = (s) => process.stderr.write(s),
|
|
63
|
+
exit = (code) => process.exit(code),
|
|
64
|
+
} = {},
|
|
65
|
+
) {
|
|
66
|
+
const refusal = refusalReason(cwd(), {
|
|
67
|
+
fs,
|
|
68
|
+
ownVersion,
|
|
69
|
+
checkAgentsDrift,
|
|
70
|
+
cwd,
|
|
71
|
+
});
|
|
72
|
+
if (refusal) {
|
|
73
|
+
writeErr(
|
|
74
|
+
`mandrel ${command}: ${refusal.what} — refusing to project ${target} from a mismatched tree.\n` +
|
|
75
|
+
` → Run \`mandrel sync\` to ${refusal.fix}, then re-run.\n`,
|
|
76
|
+
);
|
|
77
|
+
exit(1);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const syncScript = path.join(PROJECT_ROOT, '.agents', 'scripts', script);
|
|
81
|
+
const result = runner(process.execPath, [syncScript], {
|
|
82
|
+
stdio: 'inherit',
|
|
83
|
+
env: process.env,
|
|
84
|
+
});
|
|
85
|
+
const exitCode = result.status ?? 1;
|
|
86
|
+
if (exitCode !== 0) exit(exitCode);
|
|
87
|
+
}
|
package/lib/cli/registry.js
CHANGED
|
@@ -28,6 +28,7 @@ import { isCommandExcluded } from '../../.agents/scripts/lib/command-header.js';
|
|
|
28
28
|
import { getDeliveryRouting } from '../../.agents/scripts/lib/config/delivery-routing.js';
|
|
29
29
|
import { isResolvable } from '../../.agents/scripts/lib/runtime-deps/dep-resolution.js';
|
|
30
30
|
import { describeParserMajorError } from '../../.agents/scripts/lib/runtime-deps/parser-major.js';
|
|
31
|
+
import { runClaudeCodeVersion } from './claude-code-version.js';
|
|
31
32
|
import {
|
|
32
33
|
defaultResolvePackageRoot,
|
|
33
34
|
listFiles as listPayloadFiles,
|
|
@@ -958,6 +959,14 @@ export const registry = [
|
|
|
958
959
|
name: 'agents-drift',
|
|
959
960
|
run: (opts) => runAgentsDrift(opts),
|
|
960
961
|
},
|
|
962
|
+
{
|
|
963
|
+
name: 'claude-code-version',
|
|
964
|
+
run: (opts) =>
|
|
965
|
+
runClaudeCodeVersion({
|
|
966
|
+
runClaude: () => spawn('claude', ['--version'], { timeout: 10_000 }),
|
|
967
|
+
...opts,
|
|
968
|
+
}),
|
|
969
|
+
},
|
|
961
970
|
{
|
|
962
971
|
name: 'merge-driver',
|
|
963
972
|
run: (opts) => runMergeDriver(opts),
|
package/lib/cli/sync-agents.js
CHANGED
|
@@ -1,97 +1,14 @@
|
|
|
1
1
|
// lib/cli/sync-agents.js
|
|
2
|
-
/**
|
|
3
|
-
* `mandrel sync-agents`: project `.agents/agents/` into `.claude/agents/` via
|
|
4
|
-
* `.agents/scripts/sync-claude-agents.js`. Exact sibling of
|
|
5
|
-
* `sync-commands.js` — same child-process delegation, same marker-gated
|
|
6
|
-
* refusal and anchor rule (see that module's doc).
|
|
7
|
-
*/
|
|
2
|
+
/** `mandrel sync-agents`: project `.agents/agents/` into `.claude/agents/`. */
|
|
8
3
|
|
|
9
|
-
import {
|
|
10
|
-
import nodeFs from 'node:fs';
|
|
11
|
-
import path from 'node:path';
|
|
12
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { runGuardedSync } from './guarded-sync.js';
|
|
13
5
|
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
const SPEC = {
|
|
7
|
+
command: 'sync-agents',
|
|
8
|
+
target: '.claude/agents/',
|
|
9
|
+
script: 'sync-claude-agents.js',
|
|
10
|
+
};
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
|
20
|
-
const SYNC_SCRIPT = path.join(
|
|
21
|
-
PROJECT_ROOT,
|
|
22
|
-
'.agents',
|
|
23
|
-
'scripts',
|
|
24
|
-
'sync-claude-agents.js',
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {typeof nodeFs} fsImpl
|
|
29
|
-
* @returns {string}
|
|
30
|
-
*/
|
|
31
|
-
function resolveOwnPackageVersion(fsImpl) {
|
|
32
|
-
const parsed = JSON.parse(
|
|
33
|
-
fsImpl.readFileSync(path.join(PROJECT_ROOT, 'package.json'), 'utf8'),
|
|
34
|
-
);
|
|
35
|
-
return String(parsed.version);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {string[]} _argv - Unused; reserved for future flags.
|
|
40
|
-
* @param {{
|
|
41
|
-
* runner?: typeof spawnSync,
|
|
42
|
-
* cwd?: () => string,
|
|
43
|
-
* fs?: typeof nodeFs,
|
|
44
|
-
* ownVersion?: string,
|
|
45
|
-
* checkAgentsDrift?: () => { ok: boolean, detail: string },
|
|
46
|
-
* writeErr?: (s: string) => void,
|
|
47
|
-
* exit?: (code: number) => void,
|
|
48
|
-
* }} [opts]
|
|
49
|
-
* @returns {void}
|
|
50
|
-
*/
|
|
51
|
-
export default function run(
|
|
52
|
-
_argv = [],
|
|
53
|
-
{
|
|
54
|
-
runner = spawnSync,
|
|
55
|
-
cwd = () => process.cwd(),
|
|
56
|
-
fs = nodeFs,
|
|
57
|
-
ownVersion,
|
|
58
|
-
checkAgentsDrift,
|
|
59
|
-
writeErr = (s) => process.stderr.write(s),
|
|
60
|
-
exit = (code) => process.exit(code),
|
|
61
|
-
} = {},
|
|
62
|
-
) {
|
|
63
|
-
const projectRoot = cwd();
|
|
64
|
-
const resolvedOwnVersion = ownVersion ?? resolveOwnPackageVersion(fs);
|
|
65
|
-
const marker = readVersionMarker(projectRoot, fs);
|
|
66
|
-
|
|
67
|
-
if (marker) {
|
|
68
|
-
if (marker !== resolvedOwnVersion) {
|
|
69
|
-
writeErr(
|
|
70
|
-
`mandrel sync-agents: the materialized .agents/ tree is v${marker} but the running CLI is v${resolvedOwnVersion} — refusing to project .claude/agents/ from a mismatched tree.\n` +
|
|
71
|
-
' → Run `mandrel sync` to re-materialize .agents/ to the current version, then re-run.\n',
|
|
72
|
-
);
|
|
73
|
-
exit(1);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
const drift = (checkAgentsDrift ?? (() => runAgentsDrift({ cwd })))();
|
|
78
|
-
if (!drift.ok) {
|
|
79
|
-
writeErr(
|
|
80
|
-
`mandrel sync-agents: .agents/ appears to have drifted from the installed package payload (${drift.detail}) — refusing to project .claude/agents/ from a mismatched tree.\n` +
|
|
81
|
-
' → Run `mandrel sync` to restore the materialized .agents/ payload, then re-run.\n',
|
|
82
|
-
);
|
|
83
|
-
exit(1);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const result = runner(process.execPath, [SYNC_SCRIPT], {
|
|
89
|
-
stdio: 'inherit',
|
|
90
|
-
env: process.env,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const exitCode = result.status ?? 1;
|
|
94
|
-
if (exitCode !== 0) {
|
|
95
|
-
exit(exitCode);
|
|
96
|
-
}
|
|
12
|
+
export default function run(argv, opts) {
|
|
13
|
+
runGuardedSync(SPEC, argv, opts);
|
|
97
14
|
}
|
package/lib/cli/sync-commands.js
CHANGED
|
@@ -1,106 +1,14 @@
|
|
|
1
1
|
// lib/cli/sync-commands.js
|
|
2
|
-
/**
|
|
3
|
-
* `mandrel sync-commands`: delegate to `.agents/scripts/sync-claude-commands.js`
|
|
4
|
-
* in a child process (it has top-level await and no exported main), forwarding
|
|
5
|
-
* output and exit code.
|
|
6
|
-
*
|
|
7
|
-
* Refuses first when `.agents/` does not match the running CLI — otherwise
|
|
8
|
-
* commands are projected from a stale tree, and since `.claude/*` is
|
|
9
|
-
* gitignored nothing surfaces until an agent hits a missing module. With the
|
|
10
|
-
* `.agents/.mandrel-version` marker, compare it to the CLI's own version;
|
|
11
|
-
* without it, fall back to the `agents-drift` content check.
|
|
12
|
-
*
|
|
13
|
-
* `PROJECT_ROOT` (the package root) answers only "what version is this CLI";
|
|
14
|
-
* the marker is read from `cwd()`. Reading both from `PROJECT_ROOT` would
|
|
15
|
-
* compare the package with itself and never fire.
|
|
16
|
-
*/
|
|
2
|
+
/** `mandrel sync-commands`: project `.agents/workflows/` into `.claude/commands/`. */
|
|
17
3
|
|
|
18
|
-
import {
|
|
19
|
-
import nodeFs from 'node:fs';
|
|
20
|
-
import path from 'node:path';
|
|
21
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { runGuardedSync } from './guarded-sync.js';
|
|
22
5
|
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
const SPEC = {
|
|
7
|
+
command: 'sync-commands',
|
|
8
|
+
target: '.claude/commands/',
|
|
9
|
+
script: 'sync-claude-commands.js',
|
|
10
|
+
};
|
|
25
11
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
|
29
|
-
const SYNC_SCRIPT = path.join(
|
|
30
|
-
PROJECT_ROOT,
|
|
31
|
-
'.agents',
|
|
32
|
-
'scripts',
|
|
33
|
-
'sync-claude-commands.js',
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @param {typeof nodeFs} fsImpl
|
|
38
|
-
* @returns {string}
|
|
39
|
-
*/
|
|
40
|
-
function resolveOwnPackageVersion(fsImpl) {
|
|
41
|
-
const parsed = JSON.parse(
|
|
42
|
-
fsImpl.readFileSync(path.join(PROJECT_ROOT, 'package.json'), 'utf8'),
|
|
43
|
-
);
|
|
44
|
-
return String(parsed.version);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {string[]} _argv - Unused; reserved for future flags.
|
|
49
|
-
* @param {{
|
|
50
|
-
* runner?: typeof spawnSync,
|
|
51
|
-
* cwd?: () => string,
|
|
52
|
-
* fs?: typeof nodeFs,
|
|
53
|
-
* ownVersion?: string,
|
|
54
|
-
* checkAgentsDrift?: () => { ok: boolean, detail: string },
|
|
55
|
-
* writeErr?: (s: string) => void,
|
|
56
|
-
* exit?: (code: number) => void,
|
|
57
|
-
* }} [opts]
|
|
58
|
-
* @returns {void}
|
|
59
|
-
*/
|
|
60
|
-
export default function run(
|
|
61
|
-
_argv = [],
|
|
62
|
-
{
|
|
63
|
-
runner = spawnSync,
|
|
64
|
-
cwd = () => process.cwd(),
|
|
65
|
-
fs = nodeFs,
|
|
66
|
-
ownVersion,
|
|
67
|
-
checkAgentsDrift,
|
|
68
|
-
writeErr = (s) => process.stderr.write(s),
|
|
69
|
-
exit = (code) => process.exit(code),
|
|
70
|
-
} = {},
|
|
71
|
-
) {
|
|
72
|
-
const projectRoot = cwd();
|
|
73
|
-
const resolvedOwnVersion = ownVersion ?? resolveOwnPackageVersion(fs);
|
|
74
|
-
const marker = readVersionMarker(projectRoot, fs);
|
|
75
|
-
|
|
76
|
-
if (marker) {
|
|
77
|
-
if (marker !== resolvedOwnVersion) {
|
|
78
|
-
writeErr(
|
|
79
|
-
`mandrel sync-commands: the materialized .agents/ tree is v${marker} but the running CLI is v${resolvedOwnVersion} — refusing to project .claude/commands/ from a mismatched tree.\n` +
|
|
80
|
-
' → Run `mandrel sync` to re-materialize .agents/ to the current version, then re-run.\n',
|
|
81
|
-
);
|
|
82
|
-
exit(1);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
const drift = (checkAgentsDrift ?? (() => runAgentsDrift({ cwd })))();
|
|
87
|
-
if (!drift.ok) {
|
|
88
|
-
writeErr(
|
|
89
|
-
`mandrel sync-commands: .agents/ appears to have drifted from the installed package payload (${drift.detail}) — refusing to project .claude/commands/ from a mismatched tree.\n` +
|
|
90
|
-
' → Run `mandrel sync` to restore the materialized .agents/ payload, then re-run.\n',
|
|
91
|
-
);
|
|
92
|
-
exit(1);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const result = runner(process.execPath, [SYNC_SCRIPT], {
|
|
98
|
-
stdio: 'inherit',
|
|
99
|
-
env: process.env,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const exitCode = result.status ?? 1;
|
|
103
|
-
if (exitCode !== 0) {
|
|
104
|
-
exit(exitCode);
|
|
105
|
-
}
|
|
12
|
+
export default function run(argv, opts) {
|
|
13
|
+
runGuardedSync(SPEC, argv, opts);
|
|
106
14
|
}
|
package/lib/cli/uninstall.js
CHANGED
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
BOOTSTRAP_COMMAND,
|
|
22
22
|
GITIGNORE_BLOCKS,
|
|
23
23
|
SYNC_COMMAND,
|
|
24
|
+
SYSTEM_PROMPT_AGENTS_MD,
|
|
24
25
|
SYSTEM_PROMPT_BLOCK,
|
|
25
|
-
SYSTEM_PROMPT_CLAUDE_MD,
|
|
26
26
|
SYSTEM_PROMPT_IMPORT,
|
|
27
27
|
} from '../../.agents/scripts/lib/bootstrap/project-bootstrap.js';
|
|
28
28
|
import {
|
|
@@ -60,17 +60,17 @@ const FRAMEWORK_NPM_SCRIPTS = Object.freeze({
|
|
|
60
60
|
*/
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* Strip the system-prompt import block from
|
|
64
|
-
* only when byte-identical to the install template — a heading-only
|
|
65
|
-
* would delete an operator's all-headings file.
|
|
63
|
+
* Strip the system-prompt import block from a root entry doc. The file is
|
|
64
|
+
* deleted only when byte-identical to the install template — a heading-only
|
|
65
|
+
* heuristic would delete an operator's all-headings file.
|
|
66
66
|
*
|
|
67
|
+
* @param {string} rel - `AGENTS.md`, or a legacy un-migrated `CLAUDE.md`.
|
|
67
68
|
* @param {string} projectRoot
|
|
68
69
|
* @param {typeof fs} fsImpl
|
|
69
70
|
* @returns {ReversalOutcome}
|
|
70
71
|
*/
|
|
71
|
-
function
|
|
72
|
-
const target = path.join(projectRoot,
|
|
73
|
-
const rel = 'CLAUDE.md';
|
|
72
|
+
function revertEntryDoc(rel, projectRoot, fsImpl) {
|
|
73
|
+
const target = path.join(projectRoot, rel);
|
|
74
74
|
if (!fsImpl.existsSync(target)) {
|
|
75
75
|
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
76
76
|
}
|
|
@@ -78,12 +78,12 @@ function revertClaudeMd(projectRoot, fsImpl) {
|
|
|
78
78
|
if (!original.includes(SYSTEM_PROMPT_IMPORT)) {
|
|
79
79
|
return { kind: 'skipped', target: rel, detail: 'import already absent' };
|
|
80
80
|
}
|
|
81
|
-
if (original.trim() ===
|
|
81
|
+
if (original.trim() === SYSTEM_PROMPT_AGENTS_MD.trim()) {
|
|
82
82
|
fsImpl.rmSync(target, { force: true });
|
|
83
83
|
return {
|
|
84
84
|
kind: 'reverted',
|
|
85
85
|
target: rel,
|
|
86
|
-
detail:
|
|
86
|
+
detail: `removed install-created ${rel}`,
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
// Full block first, then the bare import line for a hand-edited block.
|
|
@@ -109,6 +109,33 @@ function revertClaudeMd(projectRoot, fsImpl) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* @param {string} projectRoot
|
|
114
|
+
* @param {typeof fs} fsImpl
|
|
115
|
+
* @returns {ReversalOutcome}
|
|
116
|
+
*/
|
|
117
|
+
function revertAgentsMd(projectRoot, fsImpl) {
|
|
118
|
+
return revertEntryDoc('AGENTS.md', projectRoot, fsImpl);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Pre-2.65 ledgers name CLAUDE.md. An un-migrated CLAUDE.md reverts as
|
|
123
|
+
* before; once the update migration folded it away, the wiring lives in
|
|
124
|
+
* AGENTS.md, so that is reverted instead. CLAUDE.md is never recreated.
|
|
125
|
+
*
|
|
126
|
+
* @param {string} projectRoot
|
|
127
|
+
* @param {typeof fs} fsImpl
|
|
128
|
+
* @returns {ReversalOutcome}
|
|
129
|
+
*/
|
|
130
|
+
function revertClaudeMd(projectRoot, fsImpl) {
|
|
131
|
+
const legacy = fsImpl.existsSync(path.join(projectRoot, 'CLAUDE.md'));
|
|
132
|
+
return revertEntryDoc(
|
|
133
|
+
legacy ? 'CLAUDE.md' : 'AGENTS.md',
|
|
134
|
+
projectRoot,
|
|
135
|
+
fsImpl,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
112
139
|
/**
|
|
113
140
|
* Splice the sync hook and any legacy plugin-enablement keys out of
|
|
114
141
|
* `.claude/settings.json`, keeping everything else; delete the file if empty.
|
|
@@ -405,6 +432,7 @@ function revertPreCommitHook(projectRoot, fsImpl) {
|
|
|
405
432
|
* @type {Readonly<Record<string, (root: string, fsImpl: typeof fs, executedAction?: string) => ReversalOutcome>>}
|
|
406
433
|
*/
|
|
407
434
|
const REVERSAL_BY_TARGET = Object.freeze({
|
|
435
|
+
'AGENTS.md': revertAgentsMd,
|
|
408
436
|
'CLAUDE.md': revertClaudeMd,
|
|
409
437
|
'.claude/settings.json': revertClaudeSettings,
|
|
410
438
|
'.claude/plugins/mandrel': revertClaudeCommands,
|
package/lib/migrations/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { retireDeliveryLimitKnobs } from './steps/2.57.0-retire-delivery-limit-k
|
|
|
16
16
|
import { retirePlanningLimitKnobs } from './steps/2.57.0-retire-planning-limit-knobs.js';
|
|
17
17
|
import { retireAuditResultsAutoFile } from './steps/2.60.0-retire-audit-results-autofile.js';
|
|
18
18
|
import { baselineMergeQueueShape } from './steps/2.63.0-baseline-merge-queue-shape.js';
|
|
19
|
+
import { foldClaudeMdIntoAgentsMdStep } from './steps/2.65.0-fold-claude-md-into-agents-md.js';
|
|
19
20
|
import { stripRemovedAgentrcKeys } from './steps/strip-removed-agentrc-keys.js';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -40,6 +41,7 @@ export const migrations = [
|
|
|
40
41
|
retireAuditResultsAutoFile,
|
|
41
42
|
stripRemovedAgentrcKeys,
|
|
42
43
|
baselineMergeQueueShape,
|
|
44
|
+
foldClaudeMdIntoAgentsMdStep,
|
|
43
45
|
];
|
|
44
46
|
|
|
45
47
|
export { compareVersions };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// lib/migrations/steps/2.65.0-fold-claude-md-into-agents-md.js
|
|
2
|
+
/**
|
|
3
|
+
* Fold a consumer's root CLAUDE.md into AGENTS.md and delete CLAUDE.md.
|
|
4
|
+
* The host reads CLAUDE.md exclusively whenever it exists, so a surviving one
|
|
5
|
+
* would shadow the AGENTS.md wiring. Shares the bootstrap fold contract.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import nodeFs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
foldClaudeMdIntoAgentsMd,
|
|
13
|
+
LEGACY_ENTRY_DOC,
|
|
14
|
+
} from '../../../.agents/scripts/lib/bootstrap/agents-md-fold.js';
|
|
15
|
+
|
|
16
|
+
export const foldClaudeMdIntoAgentsMdStep = {
|
|
17
|
+
version: '2.65.0',
|
|
18
|
+
description:
|
|
19
|
+
'fold the root CLAUDE.md into AGENTS.md and delete it — AGENTS.md is ' +
|
|
20
|
+
'now the entry doc (Story #5410)',
|
|
21
|
+
/**
|
|
22
|
+
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
23
|
+
* @param {typeof nodeFs} [fsImpl]
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
detect(ctx, fsImpl = ctx?.fs ?? nodeFs) {
|
|
27
|
+
const root = ctx?.projectRoot ?? process.cwd();
|
|
28
|
+
return fsImpl.existsSync(path.join(root, LEGACY_ENTRY_DOC));
|
|
29
|
+
},
|
|
30
|
+
/**
|
|
31
|
+
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
32
|
+
* @param {typeof nodeFs} [fsImpl]
|
|
33
|
+
* @returns {void}
|
|
34
|
+
*/
|
|
35
|
+
apply(ctx, fsImpl = ctx?.fs ?? nodeFs) {
|
|
36
|
+
foldClaudeMdIntoAgentsMd(ctx?.projectRoot ?? process.cwd(), fsImpl);
|
|
37
|
+
},
|
|
38
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mandrel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.66.0",
|
|
4
4
|
"description": "Claude Code-first opinionated workflow framework: instructions, skills, rules, and SDLC workflows that govern AI coding assistants.",
|
|
5
5
|
"files": [
|
|
6
6
|
".agents/",
|
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
"@cucumber/gherkin": "^42.0.1",
|
|
103
103
|
"c8": "^11.0.0",
|
|
104
104
|
"chokidar": "^5.0.0",
|
|
105
|
+
"fast-check": "^4.10.2",
|
|
105
106
|
"husky": "^9.1.7",
|
|
106
107
|
"jscpd": "^4.2.5",
|
|
107
108
|
"knip": "^6.17.1",
|
|
@@ -126,7 +127,7 @@
|
|
|
126
127
|
},
|
|
127
128
|
"peerDependencies": {
|
|
128
129
|
"@cucumber/gherkin": ">=32.0.0",
|
|
129
|
-
"typescript": ">=5.0.0"
|
|
130
|
+
"typescript": ">=5.0.0 <7"
|
|
130
131
|
},
|
|
131
132
|
"peerDependenciesMeta": {
|
|
132
133
|
"@cucumber/gherkin": {
|