mandrel 2.30.0 → 2.32.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 +4 -4
- package/.agents/docs/agentrc-reference.json +61 -57
- package/.agents/docs/configuration.md +274 -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/ci-remediation.md +44 -1
- 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 +0 -1
- package/.agents/schemas/agentrc.schema.json +1939 -1400
- 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 +7 -29
- package/.agents/scripts/apply-quality-bootstrap.js +27 -34
- 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 +136 -0
- package/.agents/scripts/check-lifecycle-lint.js +36 -112
- 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 +0 -1
- 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/temp-paths.js +6 -5
- package/.agents/scripts/lib/config-settings-schema-delivery.js +237 -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/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/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-entry-sync.js +469 -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 +6 -0
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +0 -1
- package/.agents/scripts/lib/orchestration/{lifecycle/listeners/watcher.js → pr-watch.js} +58 -208
- package/.agents/scripts/lib/orchestration/resolve-stories.js +5 -15
- 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/push.js +17 -2
- 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 +65 -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-sizing.js +1 -1
- 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/story-body.js +12 -59
- 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/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/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 +0 -2
- 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/update-dead-exports-baseline.js +321 -0
- package/.agents/skills/core/gates-and-baselines/SKILL.md +2 -2
- package/.agents/skills/skills.index.json +2 -12
- package/.agents/skills/stack/qa/playwright/SKILL.md +48 -0
- package/.agents/workflows/audit-documentation.md +5 -6
- package/.agents/workflows/audit-to-stories.md +2 -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 +2 -1
- package/.agents/workflows/helpers/deliver-story-reference.md +27 -16
- 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 +49 -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 +12 -3
- 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
|
@@ -2,30 +2,37 @@
|
|
|
2
2
|
/* node:coverage ignore file */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* check-lifecycle-lint.js — enforce the
|
|
6
|
-
*
|
|
5
|
+
* check-lifecycle-lint.js — enforce the lifecycle lint rules that biome's
|
|
6
|
+
* stock ruleset cannot express.
|
|
7
7
|
*
|
|
8
|
-
* Rule 1 — "No Promise.all over
|
|
9
|
-
* Files under `.agents/scripts/lib/orchestration/lifecycle/**`
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* `tests/lifecycle/**` are exempt — fixtures that prove the rule
|
|
8
|
+
* Rule 1 — "No Promise.all over the lifecycle surface".
|
|
9
|
+
* Files under `.agents/scripts/lib/orchestration/lifecycle/**` MUST NOT
|
|
10
|
+
* contain `Promise.all(`. The surface is the append-only ledger writer, and
|
|
11
|
+
* record ordering is the whole point of an append-only trail: a parallel
|
|
12
|
+
* write interleaves records and breaks the ordering a reader relies on.
|
|
13
|
+
* Tests under `tests/lifecycle/**` are exempt — fixtures that prove the rule
|
|
14
14
|
* bites need to carry the pattern.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
16
|
+
* (Story #5024 narrowed the rationale. It was "the bus is a strictly
|
|
17
|
+
* sequential mediator; parallelizing listeners breaks repeatability", which
|
|
18
|
+
* stopped being the reason when the bus was deleted. The rule still guards a
|
|
19
|
+
* real property of what remains.)
|
|
20
|
+
*
|
|
21
|
+
* The old Rule 2 — "wildcard-observer firewall", gating any module under
|
|
22
|
+
* `lifecycle/listeners/**` that called `bus.on('*', …)` — was deleted by
|
|
23
|
+
* Story #5024 along with the bus. Both halves of its predicate became
|
|
24
|
+
* unsatisfiable in the same commit (the directory is gone and there is no
|
|
25
|
+
* `bus` to call `.on` on), so it returned zero violations by construction
|
|
26
|
+
* rather than by verification: a gate that cannot fire, of exactly the class
|
|
27
|
+
* Story #5004 retired `check-gherkin-placeholders.js` for.
|
|
22
28
|
*
|
|
23
29
|
* Rule 3 — "Auto-merge lockout" (Story #2253 / Task #2255, Epic #2172
|
|
24
30
|
* review High-1).
|
|
25
31
|
* String literals containing the substring `gh pr merge` MUST NOT
|
|
26
32
|
* appear in any file under `.agents/scripts/**` EXCEPT
|
|
27
|
-
*
|
|
28
|
-
*
|
|
33
|
+
* `lib/orchestration/single-story-close/phases/auto-merge.js` — the v2
|
|
34
|
+
* close path that replaced the Epic-era `AutomergeArmer` listener the rule
|
|
35
|
+
* was originally written against. The original safety hole was an
|
|
29
36
|
* unconditional `gh pr merge <pr> --auto --squash --delete-branch`
|
|
30
37
|
* call in `epic-deliver-finalize.js` that armed GitHub's native
|
|
31
38
|
* auto-merge BEFORE the framework's automerge predicate evaluated
|
|
@@ -48,11 +55,12 @@
|
|
|
48
55
|
* biome + markdownlint; a custom rule fits cleanly alongside.
|
|
49
56
|
*/
|
|
50
57
|
|
|
51
|
-
import {
|
|
58
|
+
import { readFileSync } from 'node:fs';
|
|
52
59
|
import path from 'node:path';
|
|
53
60
|
import { fileURLToPath } from 'node:url';
|
|
54
61
|
|
|
55
62
|
import { runAsCli } from './lib/cli-utils.js';
|
|
63
|
+
import { walkFilesByExtension } from './lib/fs-walk.js';
|
|
56
64
|
|
|
57
65
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
58
66
|
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
@@ -65,7 +73,6 @@ const LIFECYCLE_DIR = path.join(
|
|
|
65
73
|
'orchestration',
|
|
66
74
|
'lifecycle',
|
|
67
75
|
);
|
|
68
|
-
const LISTENERS_SUBDIR = path.join(LIFECYCLE_DIR, 'listeners');
|
|
69
76
|
const SCRIPTS_DIR = path.join(REPO_ROOT, '.agents', 'scripts');
|
|
70
77
|
|
|
71
78
|
/**
|
|
@@ -102,52 +109,6 @@ const MERGE_LOCKOUT_INFRASTRUCTURE_SUFFIXES = Object.freeze([
|
|
|
102
109
|
path.join('.agents', 'scripts', 'check-lifecycle-lint.js'),
|
|
103
110
|
]);
|
|
104
111
|
|
|
105
|
-
/**
|
|
106
|
-
* Static blocklist of modules that mutate state under orchestration.
|
|
107
|
-
* Matched by `import … from '<spec>'` specifier suffix so both
|
|
108
|
-
* relative and package imports are caught. The list is small by
|
|
109
|
-
* intent — wildcard observers should not need ANY of these.
|
|
110
|
-
*
|
|
111
|
-
* Maintainers: when a future module joins the "mutates real state"
|
|
112
|
-
* club, add it here. The lint rule is the wildcard-firewall contract;
|
|
113
|
-
* the listeners SHOULD NOT bypass it.
|
|
114
|
-
*/
|
|
115
|
-
const STATE_MUTATING_MODULES = Object.freeze([
|
|
116
|
-
// GitHub state writers
|
|
117
|
-
'update-ticket-state.js',
|
|
118
|
-
'post-structured-comment.js',
|
|
119
|
-
'lib/orchestration/ticketing/state.js',
|
|
120
|
-
'lib/orchestration/ticketing/bulk.js',
|
|
121
|
-
// git / worktree mutators
|
|
122
|
-
'lib/git-utils.js',
|
|
123
|
-
'lib/orchestration/worktree-manager.js',
|
|
124
|
-
// notification writers
|
|
125
|
-
'notify.js',
|
|
126
|
-
]);
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Walk a directory tree synchronously, yielding absolute paths of files
|
|
130
|
-
* matching `.js`. The lifecycle surface is small (< 50 files in the
|
|
131
|
-
* worst case); a streaming walker is unnecessary.
|
|
132
|
-
*/
|
|
133
|
-
function* walkJs(dir) {
|
|
134
|
-
let entries;
|
|
135
|
-
try {
|
|
136
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
137
|
-
} catch (err) {
|
|
138
|
-
if (err.code === 'ENOENT') return;
|
|
139
|
-
throw err;
|
|
140
|
-
}
|
|
141
|
-
for (const entry of entries) {
|
|
142
|
-
const p = path.join(dir, entry.name);
|
|
143
|
-
if (entry.isDirectory()) {
|
|
144
|
-
yield* walkJs(p);
|
|
145
|
-
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
|
146
|
-
yield p;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
112
|
/**
|
|
152
113
|
* Rule 1 enforcement. Returns an array of `{ file, line, hint }`
|
|
153
114
|
* violations. Inline disable comments (`// lint-lifecycle-disable`) on
|
|
@@ -158,7 +119,7 @@ export function findPromiseAllViolations(
|
|
|
158
119
|
{ read = readFileSync } = {},
|
|
159
120
|
) {
|
|
160
121
|
const violations = [];
|
|
161
|
-
for (const file of
|
|
122
|
+
for (const file of walkFilesByExtension(rootDir, '.js')) {
|
|
162
123
|
const text = read(file, 'utf8');
|
|
163
124
|
const lines = text.split('\n');
|
|
164
125
|
for (let i = 0; i < lines.length; i += 1) {
|
|
@@ -169,7 +130,7 @@ export function findPromiseAllViolations(
|
|
|
169
130
|
violations.push({
|
|
170
131
|
file,
|
|
171
132
|
line: i + 1,
|
|
172
|
-
hint: 'Promise.all
|
|
133
|
+
hint: 'Promise.all on the lifecycle surface interleaves ledger writes. The ledger is append-only; writes must stay sequential.',
|
|
173
134
|
});
|
|
174
135
|
}
|
|
175
136
|
}
|
|
@@ -177,45 +138,6 @@ export function findPromiseAllViolations(
|
|
|
177
138
|
return violations;
|
|
178
139
|
}
|
|
179
140
|
|
|
180
|
-
/**
|
|
181
|
-
* Rule 2 enforcement. Returns violations for any file under
|
|
182
|
-
* `listenersDir` that BOTH (a) registers a wildcard observer
|
|
183
|
-
* (`bus.on('*', …)`) AND (b) imports a state-mutating module.
|
|
184
|
-
*
|
|
185
|
-
* Files that don't register a wildcard observer are not gated; files
|
|
186
|
-
* that wildcard-observe but only import safe modules are not gated.
|
|
187
|
-
*/
|
|
188
|
-
export function findWildcardObserverFirewallViolations(
|
|
189
|
-
listenersDir,
|
|
190
|
-
{ read = readFileSync, blocklist = STATE_MUTATING_MODULES } = {},
|
|
191
|
-
) {
|
|
192
|
-
const violations = [];
|
|
193
|
-
for (const file of walkJs(listenersDir)) {
|
|
194
|
-
const text = read(file, 'utf8');
|
|
195
|
-
const hasWildcard = /\bbus\s*\.\s*on\s*\(\s*['"`]\*['"`]/.test(text);
|
|
196
|
-
if (!hasWildcard) continue;
|
|
197
|
-
// Extract imported module specifiers — robust enough for ES module
|
|
198
|
-
// imports without parsing the full AST.
|
|
199
|
-
// `matchAll` returns an iterator of regex match arrays; using it
|
|
200
|
-
// sidesteps the assignment-in-`while` pattern biome flags as
|
|
201
|
-
// confusing.
|
|
202
|
-
for (const match of text.matchAll(/\bfrom\s+['"]([^'"]+)['"]/g)) {
|
|
203
|
-
const spec = match[1];
|
|
204
|
-
for (const banned of blocklist) {
|
|
205
|
-
if (spec === banned || spec.endsWith(`/${banned}`)) {
|
|
206
|
-
violations.push({
|
|
207
|
-
file,
|
|
208
|
-
spec,
|
|
209
|
-
hint: `Wildcard observers must not import state-mutating modules. Saw '${spec}'.`,
|
|
210
|
-
});
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return violations;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
141
|
/**
|
|
220
142
|
* Strip block (`/* … */`) and line (`// …`) comments from a source
|
|
221
143
|
* string. Pure — exported for tests so the comment-stripping contract
|
|
@@ -310,7 +232,7 @@ export function findMergeLockoutViolations(
|
|
|
310
232
|
// CLI, only the space-delimited form is.
|
|
311
233
|
const FORBIDDEN = 'gh pr merge';
|
|
312
234
|
const lineRe = /(['"`])((?:\\.|(?!\1).)*)\1/g;
|
|
313
|
-
for (const file of
|
|
235
|
+
for (const file of walkFilesByExtension(rootDir, '.js')) {
|
|
314
236
|
// Skip the armer (intentional carrier) and the lint infrastructure.
|
|
315
237
|
const allExempt = [...allowSuffixes, ...infrastructureSuffixes];
|
|
316
238
|
if (allExempt.some((suffix) => file.endsWith(suffix))) continue;
|
|
@@ -350,22 +272,24 @@ export function findMergeLockoutViolations(
|
|
|
350
272
|
async function main() {
|
|
351
273
|
// Per-rule discovery.
|
|
352
274
|
const v1 = findPromiseAllViolations(LIFECYCLE_DIR);
|
|
353
|
-
const v2 = findWildcardObserverFirewallViolations(LISTENERS_SUBDIR);
|
|
354
275
|
const v3 = findMergeLockoutViolations(SCRIPTS_DIR);
|
|
355
276
|
const all = [
|
|
356
|
-
...v1.map((v) => ({ rule: 'no-promise-all-
|
|
357
|
-
...v2.map((v) => ({ rule: 'wildcard-observer-firewall', ...v })),
|
|
277
|
+
...v1.map((v) => ({ rule: 'no-promise-all-lifecycle', ...v })),
|
|
358
278
|
...v3.map((v) => ({ rule: 'merge-lockout', ...v })),
|
|
359
279
|
];
|
|
360
280
|
if (all.length === 0) {
|
|
361
281
|
process.stdout.write(
|
|
362
|
-
'[lifecycle-lint] clean: no Promise.all
|
|
282
|
+
'[lifecycle-lint] clean: no Promise.all on the lifecycle surface; no merge-lockout violations.\n',
|
|
363
283
|
);
|
|
364
284
|
return 0;
|
|
365
285
|
}
|
|
366
286
|
for (const v of all) {
|
|
367
|
-
|
|
368
|
-
|
|
287
|
+
// Both finders always stamp a 1-based `line`, so there is no file-only
|
|
288
|
+
// fallback to render — the ternary that used to guard this was an
|
|
289
|
+
// unreachable branch (Story #5024).
|
|
290
|
+
process.stderr.write(
|
|
291
|
+
`[lifecycle-lint][${v.rule}] ${v.file}:${v.line}\n ${v.hint}\n`,
|
|
292
|
+
);
|
|
369
293
|
}
|
|
370
294
|
return 1;
|
|
371
295
|
}
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
* `` `${key}.schema.json` `` template), AND the
|
|
37
37
|
* schema's stem appears literally in a JS source as the
|
|
38
38
|
* key that would produce it. `lifecycle/` is loaded this
|
|
39
|
-
* way by `
|
|
39
|
+
* way by `lifecycle/emit-ledger-event.js`, and
|
|
40
40
|
* `baselines/` by `lib/baselines/envelope.js`.
|
|
41
41
|
*
|
|
42
42
|
* BOTH halves are required. The directory evidence alone
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
import { spawnSync } from 'node:child_process';
|
|
37
37
|
import crypto from 'node:crypto';
|
|
38
38
|
import { constants as osConstants } from 'node:os';
|
|
39
|
+
import { INTERCEPTOR_MAX_BUFFER_BYTES } from './lib/child-exec.js';
|
|
39
40
|
import { getLimits, resolveConfig } from './lib/config-resolver.js';
|
|
40
41
|
import { Logger } from './lib/Logger.js';
|
|
41
42
|
import { appendSignal } from './lib/observability/signals-writer.js';
|
|
@@ -291,10 +292,12 @@ export async function main(args = process.argv.slice(2)) {
|
|
|
291
292
|
const config = resolveConfig();
|
|
292
293
|
const limits = getLimits(config);
|
|
293
294
|
const executionTimeoutMs = limits.executionTimeoutMs;
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
|
|
295
|
+
// The interceptor's bound is deliberately *below* the framework-wide
|
|
296
|
+
// `MAX_BUFFER_BYTES` ceiling: it is a reported policy bound whose value the
|
|
297
|
+
// emitted friction row carries (`details.executionMaxBuffer`), not an
|
|
298
|
+
// overflow guard. Story #5009 moved its definition to the shared
|
|
299
|
+
// child-process surface so it is no longer a hand-copied literal here.
|
|
300
|
+
const executionMaxBuffer = INTERCEPTOR_MAX_BUFFER_BYTES;
|
|
298
301
|
|
|
299
302
|
const commandStr = cmdArgs.join(' ');
|
|
300
303
|
Logger.error(`[Diagnostic Interceptor] Executing: ${commandStr}`);
|