mandrel 2.31.0 → 2.33.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 +13 -17
- package/.agents/agents/acceptance-critic.md +1 -2
- package/.agents/docs/SDLC.md +12 -9
- package/.agents/docs/agentrc-reference.json +63 -58
- package/.agents/docs/configuration.md +275 -227
- package/.agents/docs/execution-reference.md +13 -14
- package/.agents/docs/quality-gates.md +195 -23
- package/.agents/instructions.md +2 -5
- package/.agents/rules/git-conventions-reference.md +27 -27
- package/.agents/rules/git-conventions.md +4 -2
- package/.agents/rules/known-tooling-behavior.md +66 -30
- package/.agents/rules/testing-standards.md +35 -71
- package/.agents/runtime-deps.json +2 -2
- package/.agents/schemas/agentrc.schema.json +1955 -1410
- package/.agents/schemas/lifecycle/README.md +21 -14
- package/.agents/schemas/lifecycle/ledger-record.schema.json +76 -22
- package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
- package/.agents/scripts/README.md +16 -29
- package/.agents/scripts/apply-quality-bootstrap.js +27 -34
- package/.agents/scripts/audit-to-stories.js +160 -41
- package/.agents/scripts/bootstrap.js +28 -26
- package/.agents/scripts/check-baseline-drift.js +73 -13
- package/.agents/scripts/check-baseline-scope.js +362 -0
- package/.agents/scripts/check-dead-exports.js +9 -1
- package/.agents/scripts/check-gherkin-corpus.js +508 -0
- package/.agents/scripts/check-knip-entries.js +159 -0
- package/.agents/scripts/check-lifecycle-lint.js +108 -124
- package/.agents/scripts/check-schema-references.js +1 -1
- package/.agents/scripts/diagnose-friction.js +7 -4
- package/.agents/scripts/generate-config-docs.js +263 -171
- package/.agents/scripts/install-matrix-assert.js +0 -1
- package/.agents/scripts/lib/ITicketingProvider.js +0 -58
- package/.agents/scripts/lib/audit-baselines/staleness.js +6 -6
- package/.agents/scripts/lib/audit-baselines/trend.js +7 -8
- package/.agents/scripts/lib/audit-baselines/weights.js +4 -5
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +81 -35
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +185 -0
- package/.agents/scripts/lib/baselines/envelope.js +41 -60
- package/.agents/scripts/lib/baselines/git-base.js +30 -37
- package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +103 -0
- package/.agents/scripts/lib/baselines/kinds/_crap-read.js +150 -0
- package/.agents/scripts/lib/baselines/kinds/crap.js +25 -65
- package/.agents/scripts/lib/baselines/orphan-pruner.js +233 -0
- package/.agents/scripts/lib/baselines/refresh-service.js +6 -8
- package/.agents/scripts/lib/baselines/scope-assert.js +223 -0
- package/.agents/scripts/lib/baselines/scope-inventory.js +314 -0
- package/.agents/scripts/lib/bdd-step-index.js +326 -0
- package/.agents/scripts/lib/bootstrap/install-ledger.js +5 -3
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +4 -6
- package/.agents/scripts/lib/bootstrap/manifest.js +17 -40
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +12 -59
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +62 -2
- package/.agents/scripts/lib/checks/loop-health.js +9 -37
- package/.agents/scripts/lib/child-exec.js +193 -0
- package/.agents/scripts/lib/cli/standard-args.js +1 -1
- package/.agents/scripts/lib/cli-args.js +64 -0
- package/.agents/scripts/lib/close-validation/gates.js +2 -2
- package/.agents/scripts/lib/close-validation/runner.js +3 -3
- package/.agents/scripts/lib/config/acceptance-eval.js +5 -52
- package/.agents/scripts/lib/config/commands.js +3 -5
- package/.agents/scripts/lib/config/explain.js +5 -7
- package/.agents/scripts/lib/config/gates/bundle-size.schema.js +32 -6
- package/.agents/scripts/lib/config/gates/coverage.schema.js +25 -5
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +12 -2
- package/.agents/scripts/lib/config/gates/crap.schema.js +68 -23
- package/.agents/scripts/lib/config/gates/duplication.schema.js +29 -17
- package/.agents/scripts/lib/config/gates/index.js +5 -2
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +34 -6
- package/.agents/scripts/lib/config/gates/lint.schema.js +11 -2
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +37 -15
- package/.agents/scripts/lib/config/gates/mutation.schema.js +15 -3
- package/.agents/scripts/lib/config/gates/shared.js +58 -9
- package/.agents/scripts/lib/config/github.js +0 -1
- package/.agents/scripts/lib/config/limits.js +3 -48
- package/.agents/scripts/lib/config/qa.js +105 -0
- package/.agents/scripts/lib/config/runners.js +38 -16
- package/.agents/scripts/lib/config/temp-paths.js +6 -5
- package/.agents/scripts/lib/config-settings-schema-delivery.js +245 -56
- package/.agents/scripts/lib/config-settings-schema-quality.js +209 -29
- package/.agents/scripts/lib/config-settings-schema.js +386 -39
- package/.agents/scripts/lib/crap-baseline-join.js +126 -9
- package/.agents/scripts/lib/crap-utils.js +84 -520
- package/.agents/scripts/lib/dead-exports-knip.js +79 -10
- package/.agents/scripts/lib/degraded-mode.js +2 -2
- package/.agents/scripts/lib/dependency-parser.js +20 -7
- package/.agents/scripts/lib/doc-tiers.js +3 -3
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +46 -104
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +10 -8
- package/.agents/scripts/lib/findings/provenance-field.js +135 -0
- package/.agents/scripts/lib/findings/route-finding.js +57 -8
- package/.agents/scripts/lib/fs-walk.js +52 -0
- package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
- package/.agents/scripts/lib/git-utils.js +16 -36
- package/.agents/scripts/lib/knip-config-resolver.js +181 -0
- package/.agents/scripts/lib/knip-entry-sync.js +508 -0
- package/.agents/scripts/lib/observability/metrics-ledger.js +1 -1
- package/.agents/scripts/lib/observability/runtime-friction.js +10 -0
- package/.agents/scripts/lib/observability/signal-validator.js +5 -85
- package/.agents/scripts/lib/observability/signals-writer.js +19 -62
- package/.agents/scripts/lib/observability/source-classifier.js +5 -7
- package/.agents/scripts/lib/observability/terse-result.js +3 -3
- package/.agents/scripts/lib/orchestration/behind-recovery.js +114 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +7 -8
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +34 -33
- package/.agents/scripts/lib/orchestration/code-review.js +2 -2
- package/.agents/scripts/lib/orchestration/complexity-gate.js +43 -161
- package/.agents/scripts/lib/orchestration/diff-magnitude.js +4 -4
- package/.agents/scripts/lib/orchestration/label-transitions.js +3 -2
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +12 -38
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +5 -6
- package/.agents/scripts/lib/orchestration/plan-metrics.js +2 -3
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +7 -26
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +69 -5
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +69 -13
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +49 -0
- package/.agents/scripts/lib/orchestration/{lifecycle/listeners/watcher.js → pr-watch.js} +58 -208
- package/.agents/scripts/lib/orchestration/resolve-stories.js +77 -50
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +1 -1
- package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +130 -0
- package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -16
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +37 -26
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +376 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +161 -151
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +15 -3
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +10 -15
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +5 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +157 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +0 -14
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +59 -25
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +20 -31
- package/.agents/scripts/lib/orchestration/spec-spill.js +17 -3
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +7 -6
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +2 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +4 -1
- package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -127
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +116 -1
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -1
- package/.agents/scripts/lib/orchestration/ticket-validator.js +38 -0
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +5 -5
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -4
- package/.agents/scripts/lib/orchestration/verify-tier-repair.js +107 -0
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -87
- package/.agents/scripts/lib/signals/detectors/common.js +1 -1
- package/.agents/scripts/lib/signals/index.js +8 -6
- package/.agents/scripts/lib/signals/schema.js +20 -25
- package/.agents/scripts/lib/signals/write.js +8 -8
- package/.agents/scripts/lib/story-body/footer-block.js +97 -0
- package/.agents/scripts/lib/story-body/story-body.js +18 -81
- package/.agents/scripts/lib/temp-retention.js +1 -1
- package/.agents/scripts/lib/templates/decomposer-prompts.js +16 -14
- package/.agents/scripts/lib/ticket-body-sections.js +4 -5
- package/.agents/scripts/lib/wave-runner/footprint.js +306 -0
- package/.agents/scripts/lib/wave-runner/ready-set.js +198 -181
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +13 -45
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +4 -5
- package/.agents/scripts/lib/worktree-manager.js +2 -3
- package/.agents/scripts/lint-label-vocabulary.js +2 -24
- package/.agents/scripts/pr-watch-with-update.js +7 -5
- package/.agents/scripts/providers/github/blocked-by-add.js +25 -10
- package/.agents/scripts/providers/github/cache.js +2 -2
- package/.agents/scripts/providers/github/comments.js +6 -28
- package/.agents/scripts/providers/github/compose.js +0 -15
- package/.agents/scripts/providers/github/errors.js +10 -27
- package/.agents/scripts/providers/github/request-helpers.js +1 -2
- package/.agents/scripts/providers/github/sub-issues.js +10 -218
- package/.agents/scripts/providers/github.js +4 -7
- package/.agents/scripts/prune-baseline-orphans.js +181 -0
- package/.agents/scripts/resolve-stories.js +21 -7
- package/.agents/scripts/run-lint.js +61 -61
- package/.agents/scripts/run-test-profile.js +6 -6
- package/.agents/scripts/run-verify.js +48 -30
- package/.agents/scripts/single-story-close.js +20 -0
- package/.agents/scripts/single-story-init.js +12 -35
- package/.agents/scripts/stories-wave-tick.js +192 -9
- package/.agents/scripts/update-dead-exports-baseline.js +321 -0
- package/.agents/skills/core/gates-and-baselines/SKILL.md +2 -2
- package/.agents/skills/skills.index.json +1 -11
- package/.agents/workflows/audit-documentation.md +5 -6
- package/.agents/workflows/audit-to-stories.md +28 -2
- package/.agents/workflows/helpers/audit-lens-core.md +11 -12
- package/.agents/workflows/helpers/code-quality-guardrails.md +15 -14
- package/.agents/workflows/helpers/code-review.md +3 -8
- package/.agents/workflows/helpers/deliver-reference.md +30 -2
- package/.agents/workflows/helpers/deliver-story-reference.md +84 -16
- package/.agents/workflows/helpers/plan-reference.md +76 -0
- package/.agents/workflows/helpers/worktree-lifecycle.md +1 -2
- package/.agents/workflows/mandrel-update.md +10 -10
- package/.agents/workflows/qa-assist.md +15 -20
- package/.agents/workflows/qa-explore.md +9 -8
- package/README.md +1 -1
- package/docs/CHANGELOG.md +58 -0
- package/lib/migrations/index.js +2 -0
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +127 -0
- package/package.json +14 -5
- package/.agents/schemas/lifecycle/checkpoint.written.schema.json +0 -13
- package/.agents/schemas/lifecycle/close-validate.end.schema.json +0 -18
- package/.agents/schemas/lifecycle/close-validate.start.schema.json +0 -13
- package/.agents/schemas/lifecycle/code-review.end.schema.json +0 -30
- package/.agents/schemas/lifecycle/code-review.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/intervention.recorded.schema.json +0 -15
- package/.agents/schemas/lifecycle/loop.tick.schema.json +0 -20
- package/.agents/schemas/lifecycle/notification.emitted.schema.json +0 -18
- package/.agents/schemas/lifecycle/pr.created.schema.json +0 -14
- package/.agents/schemas/lifecycle/retro.end.schema.json +0 -16
- package/.agents/schemas/lifecycle/retro.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/story.blocked.schema.json +0 -13
- package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +0 -17
- package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +0 -15
- package/.agents/schemas/lifecycle/story.merged.schema.json +0 -13
- package/.agents/scripts/check-gherkin-placeholders.js +0 -663
- package/.agents/scripts/check-lifecycle-doc-drift.js +0 -411
- package/.agents/scripts/lib/audit-suite/cli.js +0 -64
- package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +0 -202
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +0 -212
- package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +0 -104
- package/.agents/scripts/lib/checks/push-hook-parity.js +0 -106
- package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +0 -92
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +0 -81
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +0 -55
- package/.agents/scripts/lib/crap-baseline-index.js +0 -46
- package/.agents/scripts/lib/crap-utils-incremental.js +0 -113
- package/.agents/scripts/lib/dynamic-workflow/capability.js +0 -396
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -335
- package/.agents/scripts/lib/mutation/baseline-snapshot.js +0 -239
- package/.agents/scripts/lib/mutation/config-detector.js +0 -119
- package/.agents/scripts/lib/mutation/stryker-runner.js +0 -306
- package/.agents/scripts/lib/mutation/survivor-report.js +0 -160
- package/.agents/scripts/lib/observability/active-story-env.js +0 -170
- package/.agents/scripts/lib/observability/tool-trace-hook.js +0 -456
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +0 -111
- package/.agents/scripts/lib/orchestration/context-envelope.js +0 -277
- package/.agents/scripts/lib/orchestration/detectors-phase.js +0 -194
- package/.agents/scripts/lib/orchestration/lifecycle/bus.js +0 -309
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +0 -181
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +0 -229
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +0 -54
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +0 -344
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +0 -114
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +0 -37
- package/.agents/scripts/lib/orchestration/resolves-token.js +0 -127
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +0 -130
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +0 -55
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +0 -211
- package/.agents/scripts/lib/planning-corpus.js +0 -37
- package/.agents/scripts/lib/qa/coverage-report.js +0 -181
- package/.agents/scripts/lib/qa/propose-missing-test.js +0 -95
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +0 -217
- package/.agents/scripts/lib/signals/detectors/index.js +0 -14
- package/.agents/scripts/lib/signals/detectors/retry.js +0 -253
- package/.agents/scripts/lib/signals/detectors/rework.js +0 -167
- package/.agents/scripts/lib/signals/read.js +0 -268
- package/.agents/scripts/lib/signals/span-tree.js +0 -291
- package/.agents/scripts/lib/story-lifecycle.js +0 -194
- package/.agents/scripts/lib/story-plan.js +0 -379
- package/.agents/scripts/lib/util/phase-timer-state.js +0 -72
- package/.agents/scripts/lib/util/phase-timer.js +0 -163
- package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +0 -169
- package/.agents/scripts/lint-baseline.js +0 -507
- package/.agents/scripts/providers/github/prs.js +0 -103
- package/.agents/scripts/signals-view.js +0 -309
- package/.agents/scripts/story-plan.js +0 -370
- package/.agents/scripts/sync-branch-from-base.js +0 -149
- package/.agents/scripts/validate-docs-freshness.js +0 -314
- package/.agents/skills/core/diagnose-friction/SKILL.md +0 -78
- package/.agents/workflows/helpers/signals.md +0 -112
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/* node:coverage ignore file -- AJV schema declaration (data-as-code) */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { gateBase } from './shared.js';
|
|
4
4
|
|
|
5
5
|
export const LINT_GATE = {
|
|
6
6
|
type: 'object',
|
|
7
|
-
|
|
7
|
+
description:
|
|
8
|
+
'Lint-count ratchet. Floors are absolute error/warning counts; the baseline pins the current count so a regression is visible even while the floor is not yet met.',
|
|
9
|
+
properties: {
|
|
10
|
+
...gateBase({
|
|
11
|
+
enabled: true,
|
|
12
|
+
baselinePath: 'baselines/lint.json',
|
|
13
|
+
tolerance: { kind: 'absolute', value: 0 },
|
|
14
|
+
floors: { '*': { errorCount: 0 } },
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
8
17
|
additionalProperties: false,
|
|
9
18
|
};
|
|
@@ -1,29 +1,51 @@
|
|
|
1
1
|
/* node:coverage ignore file -- AJV schema declaration (data-as-code) */
|
|
2
2
|
|
|
3
|
+
import { MAINTAINABILITY_GATE_DEFAULTS } from '../quality.js';
|
|
3
4
|
import {
|
|
4
|
-
|
|
5
|
+
gateBase,
|
|
5
6
|
LIST_OR_EXTENDER_OF_STRINGS,
|
|
6
7
|
SAFE_STRING,
|
|
7
8
|
} from './shared.js';
|
|
8
9
|
|
|
9
10
|
export const MAINTAINABILITY_GATE = {
|
|
10
11
|
type: 'object',
|
|
12
|
+
description:
|
|
13
|
+
'Maintainability-index ratchet. Scores per file as the average over its methods, so deleting a small high-MI method can legitimately lower a file’s score.',
|
|
11
14
|
properties: {
|
|
12
|
-
...
|
|
13
|
-
|
|
15
|
+
...gateBase({
|
|
16
|
+
enabled: MAINTAINABILITY_GATE_DEFAULTS.enabled,
|
|
17
|
+
baselinePath: MAINTAINABILITY_GATE_DEFAULTS.baselinePath,
|
|
18
|
+
tolerance: MAINTAINABILITY_GATE_DEFAULTS.tolerance,
|
|
19
|
+
floors: MAINTAINABILITY_GATE_DEFAULTS.floors,
|
|
20
|
+
}),
|
|
21
|
+
targetDirs: {
|
|
22
|
+
...LIST_OR_EXTENDER_OF_STRINGS,
|
|
23
|
+
description:
|
|
24
|
+
"Directories whose JS sources the maintainability gate scores. Mandrel ships a `src/`-centric default; projects whose executable code lives elsewhere (e.g. this repo's `.agents/scripts/` plus `tests/`) override here. The framework default is intentionally not auto-discovered, so an override is the explicit, auditable signal.",
|
|
25
|
+
default: [...MAINTAINABILITY_GATE_DEFAULTS.targetDirs],
|
|
26
|
+
},
|
|
14
27
|
// Story #4731 — commit-subject substring that acknowledges a deliberate
|
|
15
|
-
// maintainability baseline refresh in the compared range.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
refreshTimeoutMs: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
// maintainability baseline refresh in the compared range.
|
|
29
|
+
refreshTag: {
|
|
30
|
+
...SAFE_STRING,
|
|
31
|
+
minLength: 1,
|
|
32
|
+
description:
|
|
33
|
+
"Commit-subject substring that acknowledges a deliberate maintainability baseline refresh in the compared range. Mirrors the CRAP gate's `refreshTag`; a range commit carrying it that touches the baseline file demotes head-vs-base regressions (floors still enforced).",
|
|
34
|
+
},
|
|
35
|
+
refreshTimeoutMs: {
|
|
36
|
+
type: 'integer',
|
|
37
|
+
minimum: 1,
|
|
38
|
+
description:
|
|
39
|
+
'Bounded timeout (ms) for `npm run maintainability:update` spawned by the baseline-attribution refresh path. Mirrors `coverage.timeoutMs`: a SIGKILL fired at the budget boundary maps to exit 124 so the close orchestrator can flip the Story to `agent::blocked`. Default 60000 (Story #2165).',
|
|
40
|
+
default: MAINTAINABILITY_GATE_DEFAULTS.refreshTimeoutMs,
|
|
41
|
+
},
|
|
42
|
+
ignoreGlobs: {
|
|
43
|
+
type: 'array',
|
|
44
|
+
items: { type: 'string', minLength: 1 },
|
|
45
|
+
description:
|
|
46
|
+
'Minimatch glob patterns matched against the canonicalised repo-relative path of each discovered file. Files matching any pattern are excluded from MI discovery before scoring. Orthogonal to `components` (grouping) — a file excluded here never appears in any component bucket. Absent or empty preserves the existing IGNORED_DIRS-only behaviour (Story #3217).',
|
|
47
|
+
default: [...MAINTAINABILITY_GATE_DEFAULTS.ignoreGlobs],
|
|
48
|
+
},
|
|
27
49
|
},
|
|
28
50
|
additionalProperties: false,
|
|
29
51
|
};
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
/* node:coverage ignore file -- AJV schema declaration (data-as-code) */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { gateBase, NULLABLE_NONEMPTY_SAFE_STRING } from './shared.js';
|
|
4
4
|
|
|
5
5
|
export const MUTATION_GATE = {
|
|
6
6
|
type: 'object',
|
|
7
|
+
description:
|
|
8
|
+
'Stryker mutation-score ratchet. Off in practice for most consumers — the baseline kind is registered but no framework path runs Stryker.',
|
|
7
9
|
properties: {
|
|
8
|
-
...
|
|
9
|
-
|
|
10
|
+
...gateBase({
|
|
11
|
+
enabled: true,
|
|
12
|
+
baselinePath: 'baselines/mutation.json',
|
|
13
|
+
tolerance: { kind: 'percent', value: 0 },
|
|
14
|
+
floors: { '*': { score: 60 } },
|
|
15
|
+
}),
|
|
16
|
+
strykerConfigPath: {
|
|
17
|
+
...NULLABLE_NONEMPTY_SAFE_STRING,
|
|
18
|
+
description:
|
|
19
|
+
'Repo-relative path to the Stryker config. `null` lets Stryker resolve its own default.',
|
|
20
|
+
default: null,
|
|
21
|
+
},
|
|
10
22
|
},
|
|
11
23
|
additionalProperties: false,
|
|
12
24
|
};
|
|
@@ -48,10 +48,21 @@ export const LIST_OR_EXTENDER_OF_STRINGS = {
|
|
|
48
48
|
/** Object-shaped tolerance: `{ kind: 'absolute' | 'percent', value: number }`. */
|
|
49
49
|
export const TOLERANCE_SCHEMA = {
|
|
50
50
|
type: 'object',
|
|
51
|
+
description:
|
|
52
|
+
'How much a rollup may drift from the committed baseline before the gate reports a regression.',
|
|
51
53
|
required: ['kind', 'value'],
|
|
52
54
|
properties: {
|
|
53
|
-
kind: {
|
|
54
|
-
|
|
55
|
+
kind: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
enum: ['absolute', 'percent'],
|
|
58
|
+
description:
|
|
59
|
+
'Whether `value` is read as raw metric units (`absolute`) or as a percentage of the baseline (`percent`).',
|
|
60
|
+
},
|
|
61
|
+
value: {
|
|
62
|
+
type: 'number',
|
|
63
|
+
minimum: 0,
|
|
64
|
+
description: 'The tolerance magnitude. 0 means no drift is allowed.',
|
|
65
|
+
},
|
|
55
66
|
},
|
|
56
67
|
additionalProperties: false,
|
|
57
68
|
};
|
|
@@ -84,6 +95,8 @@ export const TOLERANCE_SCHEMA = {
|
|
|
84
95
|
*/
|
|
85
96
|
export const FLOORS_SCHEMA = {
|
|
86
97
|
type: 'object',
|
|
98
|
+
description:
|
|
99
|
+
'Workspace-keyed absolute floors: `{ "<workspace>": { "<metric>": number } }`. `"*"` is the project-wide catch-all; the metric keyset is open so per-rollup keys flow through without each gate enumerating them. Floors are absolute — unlike `tolerance`, they are enforced regardless of the baseline.',
|
|
87
100
|
additionalProperties: {
|
|
88
101
|
type: 'object',
|
|
89
102
|
additionalProperties: { type: 'number' },
|
|
@@ -102,16 +115,52 @@ export const FLOORS_SCHEMA = {
|
|
|
102
115
|
*/
|
|
103
116
|
export const COMPONENTS_SCHEMA = {
|
|
104
117
|
type: 'object',
|
|
118
|
+
description:
|
|
119
|
+
'Per-gate component map — component name to the glob list whose files roll up under it. Defaults to `{ "*": ["**"] }` at the resolver layer.',
|
|
105
120
|
additionalProperties: {
|
|
106
121
|
type: 'array',
|
|
107
122
|
items: { type: 'string', minLength: 1 },
|
|
108
123
|
},
|
|
109
124
|
};
|
|
110
125
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Build the shared four-field gate base with per-gate `default` annotations
|
|
128
|
+
* layered on (Story #5007). The base fields are identical in shape across
|
|
129
|
+
* every gate but their defaults are not — each gate ships its own
|
|
130
|
+
* `baselinePath`, tolerance, and floors — so the defaults are supplied by the
|
|
131
|
+
* calling gate module rather than baked in here.
|
|
132
|
+
*
|
|
133
|
+
* @param {{ enabled?: boolean, baselinePath?: string,
|
|
134
|
+
* tolerance?: object, floors?: object }} [defaults]
|
|
135
|
+
* @returns {object} A fresh `properties` fragment; never a shared reference.
|
|
136
|
+
*/
|
|
137
|
+
export function gateBase(defaults = {}) {
|
|
138
|
+
return {
|
|
139
|
+
enabled: {
|
|
140
|
+
type: 'boolean',
|
|
141
|
+
description:
|
|
142
|
+
'When false, the checker exits 0 with a skip line and the gate is reported as `skipped`, never omitted.',
|
|
143
|
+
...(defaults.enabled === undefined ? {} : { default: defaults.enabled }),
|
|
144
|
+
},
|
|
145
|
+
baselinePath: {
|
|
146
|
+
...SAFE_STRING,
|
|
147
|
+
minLength: 1,
|
|
148
|
+
description:
|
|
149
|
+
"Repo-root-relative path to the gate's committed baseline artifact.",
|
|
150
|
+
...(defaults.baselinePath === undefined
|
|
151
|
+
? {}
|
|
152
|
+
: { default: defaults.baselinePath }),
|
|
153
|
+
},
|
|
154
|
+
tolerance: {
|
|
155
|
+
...TOLERANCE_SCHEMA,
|
|
156
|
+
...(defaults.tolerance === undefined
|
|
157
|
+
? {}
|
|
158
|
+
: { default: defaults.tolerance }),
|
|
159
|
+
},
|
|
160
|
+
floors: {
|
|
161
|
+
...FLOORS_SCHEMA,
|
|
162
|
+
...(defaults.floors === undefined ? {} : { default: defaults.floors }),
|
|
163
|
+
},
|
|
164
|
+
components: COMPONENTS_SCHEMA,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* `planning.*` and `delivery.*`:
|
|
7
7
|
*
|
|
8
8
|
* - `delivery.execution.timeoutMs` (per-process execution timeout)
|
|
9
|
-
* - `delivery.lease.ttlMs` (assignee-as-lease staleness window — Story #3480)
|
|
10
9
|
* - `delivery.signals.{rework, retry}` (performance-signal detector
|
|
11
10
|
* thresholds — `hotspot` retired with Epic #4406; `churn`/`idle` dropped)
|
|
12
11
|
*
|
|
@@ -14,7 +13,9 @@
|
|
|
14
13
|
* - `maxTickets` — decomposer reviewability budget (Story #4163)
|
|
15
14
|
*
|
|
16
15
|
* Dropped entirely: `maxInstructionSteps`, `friction.*`, `executionMaxBuffer`,
|
|
17
|
-
* `signals.{churn, idle}`, `delivery.preflight`, `delivery.
|
|
16
|
+
* `signals.{churn, idle}`, `delivery.preflight`, `delivery.lease.ttlMs`
|
|
17
|
+
* (Story #5006 deleted the lease TTL: with no heartbeat source every foreign
|
|
18
|
+
* claim read live, so the window decided nothing), `delivery.maxTokenBudget`
|
|
18
19
|
* (planning no longer sizes against a token-budget envelope; session-mass
|
|
19
20
|
* ceilings are absolute in `DEFAULT_MODEL_CAPACITY`), and
|
|
20
21
|
* `planning.context.{maxBytes, summaryMode}` (Story #4541 — the `applyBudget`
|
|
@@ -39,26 +40,12 @@ export const SIGNALS_DEFAULTS = Object.freeze({
|
|
|
39
40
|
retry: Object.freeze({ repeatCount: 3 }),
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
/**
|
|
43
|
-
* Default TTL for the assignee-as-lease primitive (Story #3480). A claim
|
|
44
|
-
* whose owner's last heartbeat is older than this window is considered stale
|
|
45
|
-
* and may be reclaimed by another operator.
|
|
46
|
-
*
|
|
47
|
-
* Note: no shipped caller supplies a real heartbeat — the emitter was inert
|
|
48
|
-
* and was deleted (A22), so the guards anchor liveness to `now` and every
|
|
49
|
-
* foreign claim reads live (fail-closed; clear a stranded claim with
|
|
50
|
-
* `--steal`). This value is therefore only consulted by a caller that threads
|
|
51
|
-
* its own `heartbeatAt`, and is kept as the documented default for that seam.
|
|
52
|
-
*/
|
|
53
|
-
export const LEASE_TTL_MS_DEFAULT = 900000;
|
|
54
|
-
|
|
55
43
|
/**
|
|
56
44
|
* Framework defaults for the surviving limits surface.
|
|
57
45
|
*/
|
|
58
46
|
export const LIMITS_DEFAULTS = Object.freeze({
|
|
59
47
|
maxTickets: 80,
|
|
60
48
|
executionTimeoutMs: 600000,
|
|
61
|
-
leaseTtlMs: LEASE_TTL_MS_DEFAULT,
|
|
62
49
|
signals: SIGNALS_DEFAULTS,
|
|
63
50
|
});
|
|
64
51
|
|
|
@@ -94,7 +81,6 @@ function mergeSignals(userSignals) {
|
|
|
94
81
|
* @returns {{
|
|
95
82
|
* maxTickets: number,
|
|
96
83
|
* executionTimeoutMs: number,
|
|
97
|
-
* leaseTtlMs: number,
|
|
98
84
|
* signals: ReturnType<typeof mergeSignals>,
|
|
99
85
|
* }}
|
|
100
86
|
*/
|
|
@@ -107,13 +93,10 @@ export function resolveLimits(config) {
|
|
|
107
93
|
delivery.execution && typeof delivery.execution === 'object'
|
|
108
94
|
? delivery.execution
|
|
109
95
|
: {};
|
|
110
|
-
const lease =
|
|
111
|
-
delivery.lease && typeof delivery.lease === 'object' ? delivery.lease : {};
|
|
112
96
|
return {
|
|
113
97
|
maxTickets: LIMITS_DEFAULTS.maxTickets,
|
|
114
98
|
executionTimeoutMs:
|
|
115
99
|
execution.timeoutMs ?? LIMITS_DEFAULTS.executionTimeoutMs,
|
|
116
|
-
leaseTtlMs: lease.ttlMs ?? LIMITS_DEFAULTS.leaseTtlMs,
|
|
117
100
|
signals: mergeSignals(delivery.signals),
|
|
118
101
|
};
|
|
119
102
|
}
|
|
@@ -141,31 +124,3 @@ export function getLimits(config) {
|
|
|
141
124
|
export function getSignals(config) {
|
|
142
125
|
return getLimits(config).signals;
|
|
143
126
|
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Resolve the assignee-as-lease TTL in milliseconds (Story #3480). Standalone
|
|
147
|
-
* accessor so the `ticket-lease` module can import it without dragging the
|
|
148
|
-
* whole limits surface into its bundle. Precedence:
|
|
149
|
-
*
|
|
150
|
-
* 1. An explicit `override` (a positive finite number) — lets a caller or
|
|
151
|
-
* test pin the TTL directly.
|
|
152
|
-
* 2. `delivery.lease.ttlMs` from the resolved config.
|
|
153
|
-
* 3. `LEASE_TTL_MS_DEFAULT`.
|
|
154
|
-
*
|
|
155
|
-
* A non-positive or non-finite override is ignored (falls through to config /
|
|
156
|
-
* default) so a stray `0` can never collapse every claim to instantly-stale.
|
|
157
|
-
*
|
|
158
|
-
* @param {object | null | undefined} config
|
|
159
|
-
* @param {number} [override]
|
|
160
|
-
* @returns {number}
|
|
161
|
-
*/
|
|
162
|
-
export function resolveLeaseTtlMs(config, override) {
|
|
163
|
-
if (
|
|
164
|
-
typeof override === 'number' &&
|
|
165
|
-
Number.isFinite(override) &&
|
|
166
|
-
override > 0
|
|
167
|
-
) {
|
|
168
|
-
return override;
|
|
169
|
-
}
|
|
170
|
-
return getLimits(config).leaseTtlMs;
|
|
171
|
-
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `qa.gherkinLint` accessor — the static Gherkin corpus gate's contract.
|
|
3
|
+
*
|
|
4
|
+
* The gate is **opt-in**: absent this block, `check-gherkin-corpus.js` reports
|
|
5
|
+
* that it is not configured and exits 0. That is not politeness. `.agents/`
|
|
6
|
+
* reaches a consumer by plain file copy, so every framework upgrade lands this
|
|
7
|
+
* gate in every project at once; a default-on corpus lint would redden the
|
|
8
|
+
* `lint` required check of every repo that happens to own a `.feature` file it
|
|
9
|
+
* never asked the framework to police.
|
|
10
|
+
*
|
|
11
|
+
* Inside the opt-in the posture inverts and the gate fails **closed** — an
|
|
12
|
+
* unresolvable parser or a scope that resolves no step definitions is an
|
|
13
|
+
* error, never a quiet pass. Both are the same blackout the gate exists to
|
|
14
|
+
* catch, wearing a different costume.
|
|
15
|
+
*
|
|
16
|
+
* Scopes are the load-bearing shape. Pooling every step root into one matcher
|
|
17
|
+
* list makes a cross-app false bind possible: a step defined only in app B's
|
|
18
|
+
* suite silently vouches for app A's feature, and the gate reports green on a
|
|
19
|
+
* corpus that cannot generate. Resolving each feature against **its own**
|
|
20
|
+
* scope's step roots makes that structurally impossible rather than merely
|
|
21
|
+
* unlikely.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Framework defaults for the two escape hatches. `@skip` is the conventional
|
|
26
|
+
* "not meant to run" tag across cucumber-js and playwright-bdd, so it is the
|
|
27
|
+
* default exemption; the waiver list starts empty because every entry is a
|
|
28
|
+
* project-specific admission that the step index guessed wrong.
|
|
29
|
+
*/
|
|
30
|
+
const GHERKIN_LINT_DEFAULTS = Object.freeze({
|
|
31
|
+
exemptionTags: Object.freeze(['@skip']),
|
|
32
|
+
stepWaivers: Object.freeze([]),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/** Coerce a value to an array of non-empty strings. */
|
|
36
|
+
function stringArray(value, fallback) {
|
|
37
|
+
if (!Array.isArray(value)) return [...fallback];
|
|
38
|
+
return value.filter((item) => typeof item === 'string' && item.length > 0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Normalize one scope entry into `{ name, featureRoots, stepRoots }`.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} name
|
|
45
|
+
* @param {object} raw
|
|
46
|
+
* @returns {{ name: string, featureRoots: string[], stepRoots: string[] }}
|
|
47
|
+
*/
|
|
48
|
+
function normalizeScope(name, raw) {
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
featureRoots: stringArray(raw?.featureRoots, []),
|
|
52
|
+
stepRoots: stringArray(raw?.stepRoots, []),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Normalize a raw `qa.gherkinLint` block.
|
|
58
|
+
*
|
|
59
|
+
* @param {object | null | undefined} raw
|
|
60
|
+
* @returns {{
|
|
61
|
+
* scopes: Array<{ name: string, featureRoots: string[], stepRoots: string[] }>,
|
|
62
|
+
* exemptionTags: string[],
|
|
63
|
+
* stepWaivers: string[],
|
|
64
|
+
* } | null} `null` when the block is absent or not an object
|
|
65
|
+
*/
|
|
66
|
+
function resolveGherkinLint(raw) {
|
|
67
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;
|
|
68
|
+
const scopesRaw =
|
|
69
|
+
raw.scopes && typeof raw.scopes === 'object' && !Array.isArray(raw.scopes)
|
|
70
|
+
? raw.scopes
|
|
71
|
+
: {};
|
|
72
|
+
return {
|
|
73
|
+
scopes: Object.keys(scopesRaw)
|
|
74
|
+
.sort()
|
|
75
|
+
.map((name) => normalizeScope(name, scopesRaw[name])),
|
|
76
|
+
exemptionTags: stringArray(
|
|
77
|
+
raw.exemptionTags,
|
|
78
|
+
GHERKIN_LINT_DEFAULTS.exemptionTags,
|
|
79
|
+
),
|
|
80
|
+
stepWaivers: stringArray(
|
|
81
|
+
raw.stepWaivers,
|
|
82
|
+
GHERKIN_LINT_DEFAULTS.stepWaivers,
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Read the normalized `qa.gherkinLint` contract off a resolved config.
|
|
89
|
+
*
|
|
90
|
+
* @param {object | null | undefined} config
|
|
91
|
+
* @returns {ReturnType<typeof resolveGherkinLint>}
|
|
92
|
+
*/
|
|
93
|
+
export function getGherkinLint(config) {
|
|
94
|
+
return resolveGherkinLint(config?.qa?.gherkinLint);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Module-private surface the suite drives directly, bundled behind one export
|
|
99
|
+
* for the same reason as `bdd-step-index.js`: `getGherkinLint` is the whole
|
|
100
|
+
* public API, and the normalizer and its defaults are how it is built.
|
|
101
|
+
*/
|
|
102
|
+
export const __testing = Object.freeze({
|
|
103
|
+
GHERKIN_LINT_DEFAULTS,
|
|
104
|
+
resolveGherkinLint,
|
|
105
|
+
});
|
|
@@ -30,9 +30,19 @@ export const DEFAULT_DECOMPOSER = Object.freeze({
|
|
|
30
30
|
* `verifyWaveResults` loop it claimed to bound never existed in the tree, and
|
|
31
31
|
* its only reader was the retired execution-analysis CLI, which echoed the
|
|
32
32
|
* number into a report rather than bounding anything.
|
|
33
|
+
*
|
|
34
|
+
* **Serialization tradeoff — `footprintGuard`.** `enforce` is the default and
|
|
35
|
+
* stays it: the file-overlap guard encodes delivery-time-only knowledge (which
|
|
36
|
+
* implementation windows are open, which Stories a foreign lease holds) that no
|
|
37
|
+
* plan-time `depends_on` edge can carry, so demoting it by default would trade
|
|
38
|
+
* a real merge-conflict class for throughput nobody asked for. `advisory`
|
|
39
|
+
* detects collisions and reports every would-be withhold but lets dispatch
|
|
40
|
+
* follow the declared edges alone — for runs whose ordering is fully declared
|
|
41
|
+
* (Story #5044).
|
|
33
42
|
*/
|
|
34
43
|
const DEFAULT_DELIVER_RUNNER = Object.freeze({
|
|
35
44
|
concurrencyCap: 3,
|
|
45
|
+
footprintGuard: 'enforce',
|
|
36
46
|
});
|
|
37
47
|
|
|
38
48
|
/**
|
|
@@ -51,28 +61,40 @@ export const DEFAULT_CODE_REVIEW = Object.freeze({
|
|
|
51
61
|
*
|
|
52
62
|
* @param {object | null | undefined} config
|
|
53
63
|
* @returns {{
|
|
54
|
-
* deliverRunner: { concurrencyCap: number },
|
|
64
|
+
* deliverRunner: { concurrencyCap: number, footprintGuard: 'enforce'|'advisory' },
|
|
55
65
|
* codeReview: { maxFixAttempts: number, maxFixScopeFiles: number, autoFixSeverity: 'high'|'medium' },
|
|
56
66
|
* decomposer: { concurrencyCap: number },
|
|
57
67
|
* }}
|
|
58
68
|
*/
|
|
59
69
|
export function getRunners(config) {
|
|
60
|
-
const deliverRunnerUser = config?.delivery?.deliverRunner ?? {};
|
|
61
|
-
const codeReviewUser = config?.delivery?.codeReview ?? {};
|
|
62
70
|
return {
|
|
63
|
-
deliverRunner:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
codeReview: {
|
|
69
|
-
maxFixAttempts:
|
|
70
|
-
codeReviewUser.maxFixAttempts ?? DEFAULT_CODE_REVIEW.maxFixAttempts,
|
|
71
|
-
maxFixScopeFiles:
|
|
72
|
-
codeReviewUser.maxFixScopeFiles ?? DEFAULT_CODE_REVIEW.maxFixScopeFiles,
|
|
73
|
-
autoFixSeverity:
|
|
74
|
-
codeReviewUser.autoFixSeverity ?? DEFAULT_CODE_REVIEW.autoFixSeverity,
|
|
75
|
-
},
|
|
71
|
+
deliverRunner: withDefaults(
|
|
72
|
+
DEFAULT_DELIVER_RUNNER,
|
|
73
|
+
config?.delivery?.deliverRunner,
|
|
74
|
+
),
|
|
75
|
+
codeReview: withDefaults(DEFAULT_CODE_REVIEW, config?.delivery?.codeReview),
|
|
76
76
|
decomposer: DEFAULT_DECOMPOSER,
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Overlay an operator's block onto the framework defaults — the per-key `??`
|
|
82
|
+
* fallback these accessors have always applied, written once.
|
|
83
|
+
*
|
|
84
|
+
* Iterating the **defaults'** keys rather than the user's is what keeps the
|
|
85
|
+
* returned shape closed: a key the framework does not define cannot reach a
|
|
86
|
+
* consumer through here even if one somehow survived AJV, so a typo degrades to
|
|
87
|
+
* the default rather than to an undefined a caller would read as configuration.
|
|
88
|
+
*
|
|
89
|
+
* @template {Record<string, unknown>} T
|
|
90
|
+
* @param {T} defaults Frozen framework defaults.
|
|
91
|
+
* @param {object|null|undefined} user Operator block from `.agentrc`.
|
|
92
|
+
* @returns {T} A fresh object; the frozen defaults are never mutated.
|
|
93
|
+
*/
|
|
94
|
+
function withDefaults(defaults, user) {
|
|
95
|
+
const out = { ...defaults };
|
|
96
|
+
for (const key of Object.keys(defaults)) {
|
|
97
|
+
if (user?.[key] != null) out[key] = user[key];
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* ├─ techspec.md
|
|
14
14
|
* ├─ manifest.md (dispatch manifest)
|
|
15
15
|
* ├─ retro.md (mirror of GitHub retro at Epic close)
|
|
16
|
-
* ├─ lifecycle.ndjson (lifecycle
|
|
16
|
+
* ├─ lifecycle.ndjson (lifecycle ledger)
|
|
17
17
|
* ├─ checkpoints/... (pre-v2 epic-runner state store; retained layout)
|
|
18
18
|
* ├─ <name> (runArtifactPath escape hatch)
|
|
19
19
|
* └─ stories/
|
|
@@ -124,7 +124,7 @@ export function _clearMainCheckoutRootCache() {
|
|
|
124
124
|
*
|
|
125
125
|
* The shared test bootstrap (`lib/test-env.js`) sets this to a fresh
|
|
126
126
|
* `os.tmpdir()` directory before spawning the test runner, so any test that
|
|
127
|
-
* reaches a writer (`signals-writer`,
|
|
127
|
+
* reaches a writer (`signals-writer`, `appendLedgerEvent`, etc.)
|
|
128
128
|
* *without* explicitly injecting an absolute tempRoot still resolves under
|
|
129
129
|
* scratch instead of the repo's real `temp/` tree. This is the single
|
|
130
130
|
* injection seam: because every path helper funnels a relative root through
|
|
@@ -573,9 +573,10 @@ function storyArtifactPath(eid, sid, name, config) {
|
|
|
573
573
|
}
|
|
574
574
|
|
|
575
575
|
/**
|
|
576
|
-
* `temp/run-<eid>/lifecycle.ndjson` — append-only lifecycle
|
|
577
|
-
* (Story #2510).
|
|
578
|
-
*
|
|
576
|
+
* `temp/run-<eid>/lifecycle.ndjson` — append-only lifecycle ledger
|
|
577
|
+
* (Story #2510). `appendLedgerEvent` persists one `emitted` record here per
|
|
578
|
+
* merge-terminal outcome; Story #5024 retired the `LedgerWriter` listener and
|
|
579
|
+
* the `TraceLogger` markdown companion that preceded it.
|
|
579
580
|
*
|
|
580
581
|
* The path is also the canonical input the standalone `lifecycle-emit`
|
|
581
582
|
* CLI feeds to `buildDefaultListenerChain` when assembling the default
|