mandrel 2.36.0 → 2.38.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/README.md +16 -16
- package/.agents/agents/plan-critic.md +1 -1
- package/.agents/docs/SDLC.md +40 -40
- package/.agents/docs/configuration.md +41 -16
- package/.agents/docs/execution-reference.md +3 -3
- package/.agents/docs/quality-gates.md +2 -2
- package/.agents/docs/workflows.md +6 -6
- package/.agents/instructions.md +5 -5
- package/.agents/rules/changelog-style.md +3 -3
- package/.agents/rules/ci-remediation.md +1 -1
- package/.agents/rules/git-conventions-reference.md +4 -4
- package/.agents/rules/testing-standards.md +56 -0
- package/.agents/schemas/agentrc.schema.json +9 -9
- package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/acceptance-eval.js +1 -1
- package/.agents/scripts/apply-quality-bootstrap.js +1 -1
- package/.agents/scripts/audit-to-stories.js +2 -2
- package/.agents/scripts/boot-sweep.js +7 -1
- package/.agents/scripts/check-context-budget.js +195 -103
- package/.agents/scripts/check-cyclomatic.js +112 -42
- package/.agents/scripts/check-doc-links.js +32 -4
- package/.agents/scripts/check-generated-validator.js +202 -0
- package/.agents/scripts/check-lifecycle-lint.js +2 -68
- package/.agents/scripts/check-schema-references.js +2 -28
- package/.agents/scripts/check-test-temp-hygiene.js +1 -1
- package/.agents/scripts/check-workflow-cli-lint.js +1 -1
- package/.agents/scripts/deliver-light.js +10 -10
- package/.agents/scripts/deliver-recover.js +1 -1
- package/.agents/scripts/drain-pending-cleanup.js +19 -2
- package/.agents/scripts/evidence-gate.js +1 -1
- package/.agents/scripts/generate-workflows-doc.js +1 -1
- package/.agents/scripts/lib/audit-suite/selector.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +5 -5
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +1 -1
- package/.agents/scripts/lib/baselines/components.js +32 -2
- package/.agents/scripts/lib/baselines/env-overrides.js +1 -1
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-budget.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
- package/.agents/scripts/lib/bdd-step-index.js +1 -1
- package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -2
- package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
- package/.agents/scripts/lib/bootstrap/install-ledger.js +1 -1
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +1 -1
- package/.agents/scripts/lib/bootstrap/prompt.js +1 -1
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +2 -2
- package/.agents/scripts/lib/checks/core-bare-clean.js +1 -1
- package/.agents/scripts/lib/checks/loop-health.js +1 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +1 -1
- package/.agents/scripts/lib/cli-args.js +1 -3
- package/.agents/scripts/lib/close-validation/gates.js +1 -1
- package/.agents/scripts/lib/close-validation/process.js +1 -1
- package/.agents/scripts/lib/command-header.js +1 -1
- package/.agents/scripts/lib/config/delivery-routing.js +1 -1
- package/.agents/scripts/lib/config/explain.js +1 -1
- package/.agents/scripts/lib/config/runners.js +2 -2
- package/.agents/scripts/lib/config/runtime.js +1 -1
- package/.agents/scripts/lib/config/sync-agentrc.js +1 -1
- package/.agents/scripts/lib/config/temp-paths.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-delivery.js +3 -3
- package/.agents/scripts/lib/config-settings-schema-quality.js +6 -6
- package/.agents/scripts/lib/config-settings-schema.js +49 -9
- package/.agents/scripts/lib/coverage-baseline.js +2 -2
- package/.agents/scripts/lib/cpu-pool.js +90 -10
- package/.agents/scripts/lib/crap-utils.js +6 -2
- package/.agents/scripts/lib/cyclomatic-ceiling.js +28 -6
- package/.agents/scripts/lib/cyclomatic-scope.js +144 -0
- package/.agents/scripts/lib/dependency-version.js +86 -0
- package/.agents/scripts/lib/duplicate-search.js +2 -2
- package/.agents/scripts/lib/errors/index.js +1 -1
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +2 -2
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +5 -5
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +2 -2
- package/.agents/scripts/lib/findings/classify-finding.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +12 -12
- package/.agents/scripts/lib/findings/route-finding.js +2 -2
- package/.agents/scripts/lib/generated/agentrc-validator.js +16 -0
- package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
- package/.agents/scripts/lib/install-cmd-parser.js +1 -1
- package/.agents/scripts/lib/knip-entry-sync.js +1 -57
- package/.agents/scripts/lib/label-constants.js +2 -2
- package/.agents/scripts/lib/label-taxonomy.js +1 -1
- package/.agents/scripts/lib/maintainability-utils.js +108 -10
- package/.agents/scripts/lib/observability/source-classifier.js +1 -0
- package/.agents/scripts/lib/onboard/init-tail.js +4 -4
- package/.agents/scripts/lib/onboard/scaffold-docs.js +2 -2
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +4 -4
- package/.agents/scripts/lib/orchestration/complexity-gate.js +5 -5
- package/.agents/scripts/lib/orchestration/deliver-recover.js +3 -3
- package/.agents/scripts/lib/orchestration/docs-digest.js +3 -3
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +2 -2
- package/.agents/scripts/lib/orchestration/light-backstop.js +1 -1
- package/.agents/scripts/lib/orchestration/light-escalation.js +6 -6
- package/.agents/scripts/lib/orchestration/light-suitability.js +19 -19
- package/.agents/scripts/lib/orchestration/plan-context.js +4 -4
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-metrics.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +3 -3
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +6 -6
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +86 -25
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +3 -3
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +6 -6
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +7 -7
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +1 -1
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +3 -3
- package/.agents/scripts/lib/orchestration/pr-watch.js +1 -30
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +2 -2
- package/.agents/scripts/lib/orchestration/remote-verifier.js +2 -2
- package/.agents/scripts/lib/orchestration/resolve-stories.js +4 -4
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +3 -3
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +1 -1
- package/.agents/scripts/lib/orchestration/review-providers/native.js +9 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +3 -3
- package/.agents/scripts/lib/orchestration/run-epilogue.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +5 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +52 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +3 -3
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +2 -5
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +14 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +1 -1
- package/.agents/scripts/lib/orchestration/ticket-lease.js +34 -9
- package/.agents/scripts/lib/orchestration/ticket-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +6 -4
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
- package/.agents/scripts/lib/preflight-runner.js +3 -3
- package/.agents/scripts/lib/qa/qa-session.js +1 -1
- package/.agents/scripts/lib/runtime-deps/manifest.js +1 -7
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +3 -58
- package/.agents/scripts/lib/signals/schema.js +1 -1
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +284 -25
- package/.agents/scripts/lib/skills/walk-skill-files.js +1 -1
- package/.agents/scripts/lib/source-text/strip-js-comments.js +115 -0
- package/.agents/scripts/lib/story-adjacency.js +2 -2
- package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
- package/.agents/scripts/lib/test-isolate/runner.js +3 -3
- package/.agents/scripts/lib/test-runner-contract.js +14 -6
- package/.agents/scripts/lib/test-tiers.js +135 -18
- package/.agents/scripts/lib/ticket-body-sections.js +1 -1
- package/.agents/scripts/lib/transpile.js +16 -3
- package/.agents/scripts/lib/util/concurrent-map.js +1 -1
- package/.agents/scripts/lib/util/parse-id-list.js +1 -1
- package/.agents/scripts/lib/wave-runner/live-probe.js +4 -4
- package/.agents/scripts/lib/wave-runner/ready-set.js +1 -1
- package/.agents/scripts/lib/workflow-closure.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +170 -32
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +2 -5
- package/.agents/scripts/lint-issue-body.js +3 -3
- package/.agents/scripts/plan-context.js +4 -4
- package/.agents/scripts/plan-critics.js +2 -2
- package/.agents/scripts/plan-persist.js +2 -2
- package/.agents/scripts/plan-run-epilogue.js +2 -2
- package/.agents/scripts/pr-watch-with-update.js +305 -137
- package/.agents/scripts/providers/github/board-add.js +1 -1
- package/.agents/scripts/providers/github/errors.js +1 -1
- package/.agents/scripts/providers/github/tickets.js +114 -21
- package/.agents/scripts/quality-preview.js +162 -70
- package/.agents/scripts/resolve-stories.js +3 -3
- package/.agents/scripts/resync-status-column.js +1 -1
- package/.agents/scripts/run-lint.js +1 -1
- package/.agents/scripts/run-test-profile.js +8 -5
- package/.agents/scripts/run-tests.js +79 -14
- package/.agents/scripts/single-story-close.js +2 -4
- package/.agents/scripts/single-story-init.js +10 -6
- package/.agents/scripts/stories-wave-tick.js +8 -8
- package/.agents/skills/core/idea-refinement/SKILL.md +5 -5
- package/.agents/skills/core/scope-triage/SKILL.md +3 -3
- package/.agents/skills/skills.index.json +1 -1
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -1
- package/.agents/workflows/audit-data-model.md +1 -1
- package/.agents/workflows/audit-documentation.md +2 -2
- package/.agents/workflows/audit-to-stories.md +11 -11
- package/.agents/workflows/git-deliver.md +4 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-review.md +4 -4
- package/.agents/workflows/helpers/deliver-light.md +26 -26
- package/.agents/workflows/helpers/deliver-reference.md +15 -7
- package/.agents/workflows/helpers/deliver-story-reference.md +9 -4
- package/.agents/workflows/helpers/deliver-story.md +6 -7
- package/.agents/workflows/helpers/diagnose.md +2 -2
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/plan-reference.md +9 -9
- package/.agents/workflows/helpers/qa-core.md +8 -8
- package/.agents/workflows/helpers/worktree-lifecycle.md +6 -6
- package/.agents/workflows/{deliver.md → mandrel-deliver.md} +15 -19
- package/.agents/workflows/{plan.md → mandrel-plan.md} +9 -9
- package/.agents/workflows/memory-consolidate.md +4 -4
- package/.agents/workflows/prototype.md +3 -3
- package/.agents/workflows/qa-assist.md +12 -12
- package/.agents/workflows/qa-explore.md +6 -6
- package/.agents/workflows/qa-run.md +1 -1
- package/README.md +7 -7
- package/docs/CHANGELOG.md +43 -0
- package/lib/cli/doctor.js +1 -1
- package/lib/cli/init.js +1 -1
- package/lib/cli/migrate.js +100 -94
- package/lib/migrations/helpers/retire-agentrc-key.js +200 -0
- package/lib/migrations/index.js +32 -33
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +21 -80
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +15 -87
- package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +13 -71
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +1 -1
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +13 -101
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +13 -100
- package/package.json +7 -3
- package/.agents/scripts/lib/audit-suite/frontmatter-lint.js +0 -32
- package/.agents/scripts/lib/baselines/maintainability-baseline-save.js +0 -37
- package/.agents/scripts/lib/cli/parse-numeric.js +0 -60
- package/.agents/scripts/lib/close-validation/telemetry.js +0 -79
- package/.agents/scripts/lib/orchestration/label-transitions.js +0 -44
- package/.agents/scripts/lib/orchestration/parked-follow-ons.js +0 -147
- package/.agents/scripts/lib/orchestration/phase-runner.js +0 -88
- package/.agents/scripts/lib/orchestration/recut.js +0 -56
package/lib/migrations/index.js
CHANGED
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
* (ascending by version) with an idempotent `detect`/`apply`.
|
|
53
53
|
*/
|
|
54
54
|
|
|
55
|
+
import { compareVersions } from '../cli/version-helpers.js';
|
|
55
56
|
import { retireMiDropKnobs } from './steps/2.1.0-retire-mi-drop-knobs.js';
|
|
56
57
|
import { retireVerifyConcurrencyCap } from './steps/2.1.0-retire-verify-concurrency-cap.js';
|
|
57
58
|
import { retireEpicAcTags } from './steps/2.2.0-retire-epic-ac-tags.js';
|
|
@@ -80,38 +81,42 @@ export const migrations = [
|
|
|
80
81
|
];
|
|
81
82
|
|
|
82
83
|
/**
|
|
83
|
-
*
|
|
84
|
-
* Non-numeric or missing segments coerce to 0 so a partial version
|
|
85
|
-
* (`'1.4'`) still compares sanely against a full one (`'1.4.0'`).
|
|
84
|
+
* The version ordering every migration decision uses.
|
|
86
85
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
86
|
+
* Re-exported from `lib/cli/version-helpers.js` — the dependency-free leaf
|
|
87
|
+
* that owns the canonical `parseVersion` / `compareVersions` pair (Story
|
|
88
|
+
* #4048 B3). The runner previously carried its own copy, so an ordering fix
|
|
89
|
+
* had to be made in three places or the copies drifted apart. Re-exporting
|
|
90
|
+
* rather than moving keeps this module's public surface intact for the
|
|
91
|
+
* callers that import `compareVersions` from here.
|
|
89
92
|
*/
|
|
90
|
-
|
|
91
|
-
const [major, minor, patch] = String(version).split('.');
|
|
92
|
-
return [
|
|
93
|
-
Number.parseInt(major, 10) || 0,
|
|
94
|
-
Number.parseInt(minor, 10) || 0,
|
|
95
|
-
Number.parseInt(patch, 10) || 0,
|
|
96
|
-
];
|
|
97
|
-
}
|
|
93
|
+
export { compareVersions };
|
|
98
94
|
|
|
99
95
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
96
|
+
* The steps that apply for an upgrade, in the order they must run:
|
|
97
|
+
* `fromVersion < step.version <= toVersion`, ascending.
|
|
98
|
+
*
|
|
99
|
+
* Exported because `mandrel migrate --dry-run` has to preview exactly what the
|
|
100
|
+
* live run would do. That preview previously re-implemented this filter and
|
|
101
|
+
* carried a comment promising it "mirrors the runner's own comparator" — a
|
|
102
|
+
* sync obligation nothing enforced, and the reason a third `compareVersions`
|
|
103
|
+
* copy existed. One selector means the preview cannot drift from the run.
|
|
103
104
|
*
|
|
104
|
-
* @param {string}
|
|
105
|
-
* @
|
|
106
|
-
* @returns {number}
|
|
105
|
+
* @param {{ registry?: Array<object>, fromVersion: string, toVersion: string }} params
|
|
106
|
+
* @returns {Array<object>}
|
|
107
107
|
*/
|
|
108
|
-
export function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
108
|
+
export function selectStepsInRange({
|
|
109
|
+
registry = migrations,
|
|
110
|
+
fromVersion,
|
|
111
|
+
toVersion,
|
|
112
|
+
}) {
|
|
113
|
+
return registry
|
|
114
|
+
.filter(
|
|
115
|
+
(step) =>
|
|
116
|
+
compareVersions(step.version, fromVersion) > 0 &&
|
|
117
|
+
compareVersions(step.version, toVersion) <= 0,
|
|
118
|
+
)
|
|
119
|
+
.sort((a, b) => compareVersions(a.version, b.version));
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
/**
|
|
@@ -152,13 +157,7 @@ export function runMigrations({
|
|
|
152
157
|
log = console.log,
|
|
153
158
|
registry = migrations,
|
|
154
159
|
} = {}) {
|
|
155
|
-
const inRange = registry
|
|
156
|
-
.filter(
|
|
157
|
-
(step) =>
|
|
158
|
-
compareVersions(step.version, fromVersion) > 0 &&
|
|
159
|
-
compareVersions(step.version, toVersion) <= 0,
|
|
160
|
-
)
|
|
161
|
-
.sort((a, b) => compareVersions(a.version, b.version));
|
|
160
|
+
const inRange = selectStepsInRange({ registry, fromVersion, toVersion });
|
|
162
161
|
|
|
163
162
|
const applied = [];
|
|
164
163
|
const skipped = [];
|
|
@@ -11,90 +11,31 @@
|
|
|
11
11
|
* sub-schemas with `additionalProperties: false`, so a consumer whose
|
|
12
12
|
* config still carries either key hits a hard AJV validation failure on
|
|
13
13
|
* upgrade, not a warning. This step strips them before that check runs.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the later retire-steps this one sweeps the committed config only:
|
|
16
|
+
* the knobs were written by the bootstrap script, never hand-pinned in an
|
|
17
|
+
* operator's `.agentrc.local.json`.
|
|
14
18
|
*/
|
|
15
19
|
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {unknown} ctx
|
|
23
|
-
* @returns {string}
|
|
24
|
-
*/
|
|
25
|
-
function resolveAgentrcPath(ctx) {
|
|
26
|
-
const projectRoot = ctx?.projectRoot ?? process.cwd();
|
|
27
|
-
return path.join(projectRoot, AGENTRC_FILENAME);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {unknown} ctx
|
|
32
|
-
* @param {typeof nodeFs} fsImpl
|
|
33
|
-
* @returns {object | null}
|
|
34
|
-
*/
|
|
35
|
-
function readAgentrcConfig(ctx, fsImpl) {
|
|
36
|
-
try {
|
|
37
|
-
const raw = fsImpl.readFileSync(resolveAgentrcPath(ctx), 'utf8');
|
|
38
|
-
return JSON.parse(raw);
|
|
39
|
-
} catch {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @param {object | null} config
|
|
46
|
-
* @returns {boolean}
|
|
47
|
-
*/
|
|
48
|
-
function hasRetiredKey(config) {
|
|
49
|
-
const guardrails = config?.delivery?.quality?.codingGuardrails;
|
|
50
|
-
const autoRefresh = config?.delivery?.quality?.autoRefresh;
|
|
51
|
-
return (
|
|
52
|
-
(Boolean(guardrails) && Object.hasOwn(guardrails, 'miDropMustRefactor')) ||
|
|
53
|
-
(Boolean(autoRefresh) && Object.hasOwn(autoRefresh, 'miDropCap'))
|
|
54
|
-
);
|
|
55
|
-
}
|
|
20
|
+
import {
|
|
21
|
+
AGENTRC_BASE_FILENAME,
|
|
22
|
+
createRetireAgentrcKeyStep,
|
|
23
|
+
} from '../helpers/retire-agentrc-key.js';
|
|
56
24
|
|
|
57
|
-
export const retireMiDropKnobs = {
|
|
25
|
+
export const retireMiDropKnobs = createRetireAgentrcKeyStep({
|
|
58
26
|
version: '2.1.0',
|
|
59
27
|
description:
|
|
60
28
|
'strip retired delivery.quality.codingGuardrails.miDropMustRefactor ' +
|
|
61
29
|
'and delivery.quality.autoRefresh.miDropCap from .agentrc.json',
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
apply(ctx) {
|
|
75
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
76
|
-
const config = readAgentrcConfig(ctx, fsImpl);
|
|
77
|
-
if (!config) return;
|
|
78
|
-
|
|
79
|
-
const guardrails = config.delivery?.quality?.codingGuardrails;
|
|
80
|
-
if (guardrails && Object.hasOwn(guardrails, 'miDropMustRefactor')) {
|
|
81
|
-
delete guardrails.miDropMustRefactor;
|
|
82
|
-
if (Object.keys(guardrails).length === 0) {
|
|
83
|
-
delete config.delivery.quality.codingGuardrails;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const autoRefresh = config.delivery?.quality?.autoRefresh;
|
|
88
|
-
if (autoRefresh && Object.hasOwn(autoRefresh, 'miDropCap')) {
|
|
89
|
-
delete autoRefresh.miDropCap;
|
|
90
|
-
if (Object.keys(autoRefresh).length === 0) {
|
|
91
|
-
delete config.delivery.quality.autoRefresh;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
fsImpl.writeFileSync(
|
|
96
|
-
resolveAgentrcPath(ctx),
|
|
97
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
98
|
-
);
|
|
99
|
-
},
|
|
100
|
-
};
|
|
30
|
+
filenames: [AGENTRC_BASE_FILENAME],
|
|
31
|
+
keys: [
|
|
32
|
+
{
|
|
33
|
+
path: ['delivery', 'quality', 'codingGuardrails', 'miDropMustRefactor'],
|
|
34
|
+
pruneDepth: 1,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
path: ['delivery', 'quality', 'autoRefresh', 'miDropCap'],
|
|
38
|
+
pruneDepth: 1,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
});
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
// lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js
|
|
2
2
|
/**
|
|
3
|
-
* Story #
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* than bounding anything; that CLI is deleted in the same Story. Setting the
|
|
10
|
-
* knob to any value only ever changed a number printed in a report.
|
|
11
|
-
*
|
|
12
|
-
* `delivery.deliverRunner` declares `additionalProperties: false`, so a
|
|
13
|
-
* consumer whose config still carries the key hits a hard AJV validation
|
|
14
|
-
* failure on upgrade — every script that resolves config, not just the one
|
|
15
|
-
* that read it. This step strips it before that check runs.
|
|
3
|
+
* Story #4531 — `delivery.deliverRunner.verifyConcurrencyCap` was retired
|
|
4
|
+
* when verification stopped being separately capped, but it stayed
|
|
5
|
+
* schema-validated in consumers' configs under a block carrying
|
|
6
|
+
* `additionalProperties: false`, so a config still setting it fails AJV
|
|
7
|
+
* validation on upgrade rather than warning. This step strips it before
|
|
8
|
+
* that check runs.
|
|
16
9
|
*
|
|
17
10
|
* Unlike the 2.1.0 mi-drop step, this one also sweeps `.agentrc.local.json`:
|
|
18
11
|
* the resolver deep-merges the local override over `.agentrc.json` and
|
|
@@ -20,82 +13,17 @@
|
|
|
20
13
|
* same way a key in the committed file does.
|
|
21
14
|
*/
|
|
22
15
|
|
|
23
|
-
import
|
|
24
|
-
import path from 'node:path';
|
|
25
|
-
|
|
26
|
-
const AGENTRC_FILENAMES = ['.agentrc.json', '.agentrc.local.json'];
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @param {unknown} ctx
|
|
30
|
-
* @param {string} filename
|
|
31
|
-
* @returns {string}
|
|
32
|
-
*/
|
|
33
|
-
function resolveAgentrcPath(ctx, filename) {
|
|
34
|
-
const projectRoot = ctx?.projectRoot ?? process.cwd();
|
|
35
|
-
return path.join(projectRoot, filename);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {unknown} ctx
|
|
40
|
-
* @param {string} filename
|
|
41
|
-
* @param {typeof nodeFs} fsImpl
|
|
42
|
-
* @returns {object | null}
|
|
43
|
-
*/
|
|
44
|
-
function readAgentrcConfig(ctx, filename, fsImpl) {
|
|
45
|
-
try {
|
|
46
|
-
const raw = fsImpl.readFileSync(resolveAgentrcPath(ctx, filename), 'utf8');
|
|
47
|
-
return JSON.parse(raw);
|
|
48
|
-
} catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
16
|
+
import { createRetireAgentrcKeyStep } from '../helpers/retire-agentrc-key.js';
|
|
52
17
|
|
|
53
|
-
|
|
54
|
-
* @param {object | null} config
|
|
55
|
-
* @returns {boolean}
|
|
56
|
-
*/
|
|
57
|
-
function hasRetiredKey(config) {
|
|
58
|
-
const deliverRunner = config?.delivery?.deliverRunner;
|
|
59
|
-
return (
|
|
60
|
-
Boolean(deliverRunner) &&
|
|
61
|
-
Object.hasOwn(deliverRunner, 'verifyConcurrencyCap')
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const retireVerifyConcurrencyCap = {
|
|
18
|
+
export const retireVerifyConcurrencyCap = createRetireAgentrcKeyStep({
|
|
66
19
|
version: '2.1.0',
|
|
67
20
|
description:
|
|
68
21
|
'strip retired delivery.deliverRunner.verifyConcurrencyCap from ' +
|
|
69
22
|
'.agentrc.json and .agentrc.local.json',
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
hasRetiredKey(readAgentrcConfig(ctx, filename, fsImpl)),
|
|
78
|
-
);
|
|
79
|
-
},
|
|
80
|
-
/**
|
|
81
|
-
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
82
|
-
* @returns {void}
|
|
83
|
-
*/
|
|
84
|
-
apply(ctx) {
|
|
85
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
86
|
-
for (const filename of AGENTRC_FILENAMES) {
|
|
87
|
-
const config = readAgentrcConfig(ctx, filename, fsImpl);
|
|
88
|
-
if (!hasRetiredKey(config)) continue;
|
|
89
|
-
|
|
90
|
-
delete config.delivery.deliverRunner.verifyConcurrencyCap;
|
|
91
|
-
if (Object.keys(config.delivery.deliverRunner).length === 0) {
|
|
92
|
-
delete config.delivery.deliverRunner;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
fsImpl.writeFileSync(
|
|
96
|
-
resolveAgentrcPath(ctx, filename),
|
|
97
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
};
|
|
23
|
+
keys: [
|
|
24
|
+
{
|
|
25
|
+
path: ['delivery', 'deliverRunner', 'verifyConcurrencyCap'],
|
|
26
|
+
pruneDepth: 1,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
});
|
|
@@ -12,81 +12,23 @@
|
|
|
12
12
|
* `maxSeedWords` hits a hard validation failure on upgrade, not a
|
|
13
13
|
* warning. This step strips the key before that check runs — the same
|
|
14
14
|
* contract-cutover pattern as `2.1.0-retire-mi-drop-knobs.js`.
|
|
15
|
+
*
|
|
16
|
+
* `planning` is an optional block, so an emptied `complexityGate` and an
|
|
17
|
+
* emptied `planning` are both pruned rather than left as orphan objects.
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param {unknown} ctx
|
|
24
|
-
* @returns {string}
|
|
25
|
-
*/
|
|
26
|
-
function resolveAgentrcPath(ctx) {
|
|
27
|
-
const projectRoot = ctx?.projectRoot ?? process.cwd();
|
|
28
|
-
return path.join(projectRoot, AGENTRC_FILENAME);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {unknown} ctx
|
|
33
|
-
* @param {typeof nodeFs} fsImpl
|
|
34
|
-
* @returns {object | null}
|
|
35
|
-
*/
|
|
36
|
-
function readAgentrcConfig(ctx, fsImpl) {
|
|
37
|
-
try {
|
|
38
|
-
const raw = fsImpl.readFileSync(resolveAgentrcPath(ctx), 'utf8');
|
|
39
|
-
return JSON.parse(raw);
|
|
40
|
-
} catch {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {object | null} config
|
|
47
|
-
* @returns {boolean}
|
|
48
|
-
*/
|
|
49
|
-
function hasRetiredKey(config) {
|
|
50
|
-
const gate = config?.planning?.complexityGate;
|
|
51
|
-
return Boolean(gate) && Object.hasOwn(gate, 'maxSeedWords');
|
|
52
|
-
}
|
|
20
|
+
import {
|
|
21
|
+
AGENTRC_BASE_FILENAME,
|
|
22
|
+
createRetireAgentrcKeyStep,
|
|
23
|
+
} from '../helpers/retire-agentrc-key.js';
|
|
53
24
|
|
|
54
|
-
export const retireMaxSeedWords = {
|
|
25
|
+
export const retireMaxSeedWords = createRetireAgentrcKeyStep({
|
|
55
26
|
version: '2.11.0',
|
|
56
27
|
description:
|
|
57
28
|
'strip retired planning.complexityGate.maxSeedWords from .agentrc.json ' +
|
|
58
29
|
'(complexity routes on Story shape, never seed word count — Story #4722)',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
65
|
-
return hasRetiredKey(readAgentrcConfig(ctx, fsImpl));
|
|
66
|
-
},
|
|
67
|
-
/**
|
|
68
|
-
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
69
|
-
* @returns {void}
|
|
70
|
-
*/
|
|
71
|
-
apply(ctx) {
|
|
72
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
73
|
-
const config = readAgentrcConfig(ctx, fsImpl);
|
|
74
|
-
if (!config) return;
|
|
75
|
-
|
|
76
|
-
const gate = config.planning?.complexityGate;
|
|
77
|
-
if (gate && Object.hasOwn(gate, 'maxSeedWords')) {
|
|
78
|
-
delete gate.maxSeedWords;
|
|
79
|
-
if (Object.keys(gate).length === 0) {
|
|
80
|
-
delete config.planning.complexityGate;
|
|
81
|
-
if (Object.keys(config.planning).length === 0) {
|
|
82
|
-
delete config.planning;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
fsImpl.writeFileSync(
|
|
88
|
-
resolveAgentrcPath(ctx),
|
|
89
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
90
|
-
);
|
|
91
|
-
},
|
|
92
|
-
};
|
|
30
|
+
filenames: [AGENTRC_BASE_FILENAME],
|
|
31
|
+
keys: [
|
|
32
|
+
{ path: ['planning', 'complexityGate', 'maxSeedWords'], pruneDepth: 2 },
|
|
33
|
+
],
|
|
34
|
+
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* from consumer feature files.
|
|
5
5
|
*
|
|
6
6
|
* The v2 Epic removal deleted `acceptance-spec-reconciler.js`, the only
|
|
7
|
-
* consumer of the namespaced per-Epic AC tags, and the `/plan` authoring
|
|
7
|
+
* consumer of the namespaced per-Epic AC tags, and the `/mandrel-plan` authoring
|
|
8
8
|
* prompt no longer mandates them. Surviving tags in consumer `.feature`
|
|
9
9
|
* files are inert and violate the gherkin-standards tag taxonomy's
|
|
10
10
|
* no-ad-hoc-tags rule, so this step removes them: each `@epic-<digits>-ac-<digits>`
|
|
@@ -1,113 +1,25 @@
|
|
|
1
1
|
// lib/migrations/steps/2.20.0-retire-codebase-snapshot.js
|
|
2
2
|
/**
|
|
3
3
|
* Story #4811 — strip the retired `planning.codebaseSnapshot` block from a
|
|
4
|
-
* consumer's `.agentrc.json`
|
|
5
|
-
*
|
|
6
|
-
* #4811 hard-cutover-removed the `/plan` codebase snapshot: the pre-computed
|
|
7
|
-
* structural view grounded nothing it promised (its default include globs
|
|
8
|
-
* missed the standard monorepo layout, and its knobs only re-filtered the same
|
|
9
|
-
* matched set), and spec authoring is grounded instead by the author's own
|
|
10
|
-
* targeted repo retrieval plus the Phase 8 `validateStoryFileAssumptions`
|
|
11
|
-
* gate. The whole block was dropped from the runtime AJV schema and the
|
|
12
|
-
* published mirror. `planning` carries `additionalProperties: false`, so a
|
|
13
|
-
* consumer whose config still sets `codebaseSnapshot` hits a hard validation
|
|
14
|
-
* failure on upgrade, not a warning. This step strips the key before that
|
|
15
|
-
* check runs — the same contract-cutover pattern as
|
|
16
|
-
* `2.11.0-retire-max-seed-words.js`, widened to the local override file
|
|
17
|
-
* because a snapshot narrowed for one checkout is exactly the kind of knob an
|
|
4
|
+
* consumer's `.agentrc.json` and from the `.agentrc.local.json` overlay an
|
|
18
5
|
* operator pins in `.agentrc.local.json`.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import nodeFs from 'node:fs';
|
|
22
|
-
import path from 'node:path';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Both config files the resolver deep-merges. A key surviving in either one
|
|
26
|
-
* fails validation, so both are stripped.
|
|
27
|
-
*/
|
|
28
|
-
const AGENTRC_FILENAMES = ['.agentrc.json', '.agentrc.local.json'];
|
|
29
|
-
|
|
30
|
-
const RETIRED_KEY = 'codebaseSnapshot';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param {unknown} ctx
|
|
34
|
-
* @param {string} filename
|
|
35
|
-
* @returns {string}
|
|
36
|
-
*/
|
|
37
|
-
function resolveAgentrcPath(ctx, filename) {
|
|
38
|
-
const projectRoot = ctx?.projectRoot ?? process.cwd();
|
|
39
|
-
return path.join(projectRoot, filename);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param {unknown} ctx
|
|
44
|
-
* @param {string} filename
|
|
45
|
-
* @param {typeof nodeFs} fsImpl
|
|
46
|
-
* @returns {object | null}
|
|
47
|
-
*/
|
|
48
|
-
function readAgentrcConfig(ctx, filename, fsImpl) {
|
|
49
|
-
try {
|
|
50
|
-
const raw = fsImpl.readFileSync(resolveAgentrcPath(ctx, filename), 'utf8');
|
|
51
|
-
return JSON.parse(raw);
|
|
52
|
-
} catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @param {object | null} config
|
|
59
|
-
* @returns {boolean}
|
|
60
|
-
*/
|
|
61
|
-
function hasRetiredKey(config) {
|
|
62
|
-
const planning = config?.planning;
|
|
63
|
-
return Boolean(planning) && Object.hasOwn(planning, RETIRED_KEY);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Strip the key and prune the containers it emptied, so a config that carried
|
|
68
|
-
* nothing but the snapshot does not keep an orphan `planning: {}`.
|
|
69
6
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
7
|
+
* Spec authoring is grounded by targeted retrieval plus the Phase 8
|
|
8
|
+
* file-assumption gate, so the snapshot block has no consumer; the block
|
|
9
|
+
* carries `additionalProperties: false`, so a config still setting it fails
|
|
10
|
+
* validation on upgrade rather than warning.
|
|
11
|
+
*
|
|
12
|
+
* `planning` is optional, so a config that carried nothing but the snapshot
|
|
13
|
+
* does not keep an orphan `planning: {}`.
|
|
72
14
|
*/
|
|
73
|
-
function stripRetiredKey(config) {
|
|
74
|
-
delete config.planning[RETIRED_KEY];
|
|
75
|
-
if (Object.keys(config.planning).length === 0) {
|
|
76
|
-
delete config.planning;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
15
|
|
|
80
|
-
|
|
16
|
+
import { createRetireAgentrcKeyStep } from '../helpers/retire-agentrc-key.js';
|
|
17
|
+
|
|
18
|
+
export const retireCodebaseSnapshot = createRetireAgentrcKeyStep({
|
|
81
19
|
version: '2.20.0',
|
|
82
20
|
description:
|
|
83
21
|
'strip retired planning.codebaseSnapshot from .agentrc.json / ' +
|
|
84
22
|
'.agentrc.local.json (spec authoring is grounded by targeted retrieval ' +
|
|
85
23
|
'plus the Phase 8 file-assumption gate — Story #4811)',
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* @returns {boolean}
|
|
89
|
-
*/
|
|
90
|
-
detect(ctx) {
|
|
91
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
92
|
-
return AGENTRC_FILENAMES.some((filename) =>
|
|
93
|
-
hasRetiredKey(readAgentrcConfig(ctx, filename, fsImpl)),
|
|
94
|
-
);
|
|
95
|
-
},
|
|
96
|
-
/**
|
|
97
|
-
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
98
|
-
* @returns {void}
|
|
99
|
-
*/
|
|
100
|
-
apply(ctx) {
|
|
101
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
102
|
-
for (const filename of AGENTRC_FILENAMES) {
|
|
103
|
-
const config = readAgentrcConfig(ctx, filename, fsImpl);
|
|
104
|
-
if (!hasRetiredKey(config)) continue;
|
|
105
|
-
|
|
106
|
-
stripRetiredKey(config);
|
|
107
|
-
fsImpl.writeFileSync(
|
|
108
|
-
resolveAgentrcPath(ctx, filename),
|
|
109
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
};
|
|
24
|
+
keys: [{ path: ['planning', 'codebaseSnapshot'], pruneDepth: 1 }],
|
|
25
|
+
});
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
// lib/migrations/steps/2.32.0-retire-lint-baseline-command.js
|
|
2
2
|
/**
|
|
3
|
-
* Story #5004
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `lib/orchestration/lint-baseline-service.js`: the CLI spawned the configured
|
|
8
|
-
* command and parsed ESLint-shaped JSON, a shape this repo's own `npm run
|
|
9
|
-
* lint` (Biome + markdownlint fan-out) never produced, and nothing invoked the
|
|
10
|
-
* service. The key left the runtime AJV schema, the published mirror,
|
|
11
|
-
* `.agentrc.json` and `agentrc-reference.json` in the same change.
|
|
12
|
-
*
|
|
13
|
-
* `project.commands` carries `additionalProperties: false`, so a consumer
|
|
14
|
-
* whose config still sets `lintBaseline` hits a hard validation failure on
|
|
15
|
-
* upgrade, not a warning. This step strips the key before that check runs —
|
|
16
|
-
* the same contract-cutover pattern as `2.11.0-retire-max-seed-words.js`.
|
|
3
|
+
* Story #5004 — strip the retired `project.commands.lintBaseline` from a
|
|
4
|
+
* consumer's config. The framework-owned lint-baseline capture CLI is gone,
|
|
5
|
+
* and the `commands` block carries `additionalProperties: false`, so a
|
|
6
|
+
* config still naming the command fails validation on upgrade.
|
|
17
7
|
*
|
|
18
8
|
* It sweeps **both** config surfaces. `config-resolver.js` deep-merges
|
|
19
9
|
* `.agentrc.local.json` over `.agentrc.json` and validates the result, so a
|
|
@@ -27,6 +17,11 @@
|
|
|
27
17
|
* `baselines/lint.json`; only the framework-owned capture shell is gone, so
|
|
28
18
|
* nothing here touches the baseline file or the gate config.
|
|
29
19
|
*
|
|
20
|
+
* An emptied `commands` block is deliberately left in place (`pruneDepth: 0`):
|
|
21
|
+
* unlike `planning.complexityGate`, `project` is a required block and an empty
|
|
22
|
+
* `commands` object is valid against the schema, so pruning it would be a
|
|
23
|
+
* cosmetic edit to a config the consumer owns.
|
|
24
|
+
*
|
|
30
25
|
* This step is also the carrier for the release note #5004 never emitted: its
|
|
31
26
|
* commit ships the `BREAKING CHANGE:` footer that the squash subject on `main`
|
|
32
27
|
* (`227e1af4`) lacks, and which release-please therefore could not surface.
|
|
@@ -34,94 +29,12 @@
|
|
|
34
29
|
* fix that stops the next one being lost.
|
|
35
30
|
*/
|
|
36
31
|
|
|
37
|
-
import
|
|
38
|
-
import path from 'node:path';
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Both config surfaces the resolver reads. `.agentrc.local.json` is deep-merged
|
|
42
|
-
* over the base *before* the AJV gate runs
|
|
43
|
-
* (`.agents/scripts/lib/config-resolver.js`), so a `lintBaseline` surviving in
|
|
44
|
-
* the overlay fails validation exactly as one in the base would — and a step
|
|
45
|
-
* that swept only the base would leave that consumer hard-broken with no
|
|
46
|
-
* self-service remedy, since re-running `mandrel update` would keep reporting
|
|
47
|
-
* clean. The overlay is operator-owned and gitignored, which is why it is easy
|
|
48
|
-
* to forget and why the sweep has to name it explicitly.
|
|
49
|
-
*/
|
|
50
|
-
const AGENTRC_FILENAMES = Object.freeze([
|
|
51
|
-
'.agentrc.json',
|
|
52
|
-
'.agentrc.local.json',
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param {unknown} ctx
|
|
57
|
-
* @param {string} filename
|
|
58
|
-
* @returns {string}
|
|
59
|
-
*/
|
|
60
|
-
function resolveAgentrcPath(ctx, filename) {
|
|
61
|
-
const projectRoot = ctx?.projectRoot ?? process.cwd();
|
|
62
|
-
return path.join(projectRoot, filename);
|
|
63
|
-
}
|
|
32
|
+
import { createRetireAgentrcKeyStep } from '../helpers/retire-agentrc-key.js';
|
|
64
33
|
|
|
65
|
-
|
|
66
|
-
* @param {unknown} ctx
|
|
67
|
-
* @param {typeof nodeFs} fsImpl
|
|
68
|
-
* @param {string} filename
|
|
69
|
-
* @returns {object | null}
|
|
70
|
-
*/
|
|
71
|
-
function readAgentrcConfig(ctx, fsImpl, filename) {
|
|
72
|
-
try {
|
|
73
|
-
const raw = fsImpl.readFileSync(resolveAgentrcPath(ctx, filename), 'utf8');
|
|
74
|
-
return JSON.parse(raw);
|
|
75
|
-
} catch {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @param {object | null} config
|
|
82
|
-
* @returns {boolean}
|
|
83
|
-
*/
|
|
84
|
-
function hasRetiredKey(config) {
|
|
85
|
-
const commands = config?.project?.commands;
|
|
86
|
-
return Boolean(commands) && Object.hasOwn(commands, 'lintBaseline');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export const retireLintBaselineCommand = {
|
|
34
|
+
export const retireLintBaselineCommand = createRetireAgentrcKeyStep({
|
|
90
35
|
version: '2.32.0',
|
|
91
36
|
description:
|
|
92
37
|
'strip retired project.commands.lintBaseline from .agentrc.json ' +
|
|
93
38
|
'(the framework lint-baseline capture CLI is gone — Story #5004)',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* @returns {boolean}
|
|
97
|
-
*/
|
|
98
|
-
detect(ctx) {
|
|
99
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
100
|
-
return AGENTRC_FILENAMES.some((filename) =>
|
|
101
|
-
hasRetiredKey(readAgentrcConfig(ctx, fsImpl, filename)),
|
|
102
|
-
);
|
|
103
|
-
},
|
|
104
|
-
/**
|
|
105
|
-
* @param {{ projectRoot?: string, fs?: typeof nodeFs }} [ctx]
|
|
106
|
-
* @returns {void}
|
|
107
|
-
*/
|
|
108
|
-
apply(ctx) {
|
|
109
|
-
const fsImpl = ctx?.fs ?? nodeFs;
|
|
110
|
-
for (const filename of AGENTRC_FILENAMES) {
|
|
111
|
-
const config = readAgentrcConfig(ctx, fsImpl, filename);
|
|
112
|
-
// An absent overlay is the common case, not an error.
|
|
113
|
-
if (!config || !hasRetiredKey(config)) continue;
|
|
114
|
-
|
|
115
|
-
delete config.project.commands.lintBaseline;
|
|
116
|
-
// An emptied `commands` block is left in place: unlike
|
|
117
|
-
// `planning.complexityGate`, `project` is a required block and an empty
|
|
118
|
-
// `commands` object is valid against the schema, so pruning it would be
|
|
119
|
-
// a cosmetic edit to a config the consumer owns.
|
|
120
|
-
|
|
121
|
-
fsImpl.writeFileSync(
|
|
122
|
-
resolveAgentrcPath(ctx, filename),
|
|
123
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
};
|
|
39
|
+
keys: [{ path: ['project', 'commands', 'lintBaseline'], pruneDepth: 0 }],
|
|
40
|
+
});
|