@magnusekdahl/parallix 1.3.4 → 1.5.126
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/NOTICES +1423 -0
- package/README.md +76 -103
- package/build/asset-manifest.json +129 -0
- package/{config → build/config}/agents.json +4 -8
- package/build/manifest.sha256 +40 -0
- package/build/migrations/0001-initial-schema.sql +91 -0
- package/build/migrations/0002-import-history.sql +16 -0
- package/build/migrations/0003-board-lane-events.sql +72 -0
- package/build/migrations/0004-mission-aggregate.sql +151 -0
- package/build/migrations/0005-mission-external-task-ref.sql +18 -0
- package/build/migrations/0005-repository-scoped-session-markers.sql +47 -0
- package/build/migrations/0006-session-markers.sql +35 -0
- package/build/migrations/0007-usage-statistics-identity.sql +60 -0
- package/build/migrations/0008-review-workflow-state.sql +61 -0
- package/build/migrations/0009-review-gate-retries.sql +16 -0
- package/build/migrations/0010-review-events-and-implementer-response.sql +64 -0
- package/build/migrations/0011-board-lane-events-repository-id.sql +89 -0
- package/build/migrations/0012-review-hook-retries.sql +11 -0
- package/build/migrations/0013-usage-statistics-thoughts-tokens.sql +11 -0
- package/build/migrations/0014-remove-usage-closed.sql +33 -0
- package/build/migrations/0015-current-work-latest-per-mission.sql +5 -0
- package/build/migrations/0016-review-drop-retry-counters.sql +21 -0
- package/build/migrations/0017-retire-mission-import-provenance.sql +5 -0
- package/build/migrations/0018-adhoc-mission-counter.sql +19 -0
- package/build/migrations/0019-custom-agent-leases.sql +12 -0
- package/build/package.json +5 -0
- package/{prompts/act-on-review.md → build/prompts/act-on-review-core.md} +6 -4
- package/build/prompts/act-on-review.md +1 -0
- package/{prompts/draft.md → build/prompts/draft-core.md} +8 -1
- package/build/prompts/execute-core.md +37 -0
- package/build/prompts/execute.md +0 -0
- package/build/prompts/review-core.md +71 -0
- package/build/prompts/review.md +0 -0
- package/build/px.mjs +1226 -0
- package/build/px.mjs.map +7 -0
- package/build/sbom.json +2155 -0
- package/build/templates/mission-scaffold.md +61 -0
- package/build/web/assets/index-B8Hv3ORh.js +9 -0
- package/build/web/assets/index-DYY4ROtr.css +1 -0
- package/build/web/index.html +13 -0
- package/build/web/manifest.json +20 -0
- package/package.json +56 -30
- package/CHANGELOG.md +0 -140
- package/config/agents.local.json.template +0 -8
- package/config/integration-pipelines.json +0 -14
- package/config/state-map.json.template +0 -31
- package/config/workflow.config.schema.json +0 -110
- package/docs/adr/0031-ai-agent-instruction-boundary-and-command-floor.md +0 -114
- package/docs/adr/0032-mission-refinement-state-and-usage-budget-signals.md +0 -137
- package/docs/adr/0034-module-and-skill-invocation-model.md +0 -202
- package/docs/adr/0036-mission-sizing-and-dependency-wave-heuristics.md +0 -81
- package/docs/adr/0037-ai-workflow-coordination-architecture.md +0 -162
- package/docs/adr/0041-integration-pipeline-gates.md +0 -165
- package/docs/adr/0042-workflow-cli-color-rendering-approach.md +0 -106
- package/docs/adr/0043-git-target-resolution-strategy.md +0 -185
- package/docs/adr/0044-workflow-distribution-model.md +0 -277
- package/docs/adr/0045-parallax-branch-model.md +0 -182
- package/docs/adr/0046-npm-publish-process-and-security.md +0 -138
- package/docs/adr/0047-per-mission-change-size-budget.md +0 -161
- package/docs/adr/0048-fail-closed-harness-defense-against-agent-hallucinations.md +0 -161
- package/docs/adr/index.md +0 -23
- package/docs/agents.md +0 -212
- package/docs/authority-reference.md +0 -328
- package/docs/doc-standards.md +0 -89
- package/docs/forgejo-setup.md +0 -55
- package/docs/migration/extraction.md +0 -61
- package/docs/migration/task-classification.md +0 -36
- package/docs/operator-setup.md +0 -76
- package/docs/readme-rewrite-benchmark.md +0 -188
- package/docs/use-cases.md +0 -149
- package/examples/README.md +0 -62
- package/examples/run-enterprise-tarball-workflow-smoke.sh +0 -257
- package/examples/run-verify-env-smoke.sh +0 -40
- package/index.js +0 -262
- package/lib/README.md +0 -13
- package/lib/agents/agents.js +0 -880
- package/lib/agents/agents.ts +0 -978
- package/lib/agents/claude-telemetry.js +0 -232
- package/lib/agents/claude-telemetry.ts +0 -233
- package/lib/agents/claude.js +0 -152
- package/lib/agents/claude.ts +0 -158
- package/lib/agents/codex-telemetry.js +0 -227
- package/lib/agents/codex-telemetry.ts +0 -205
- package/lib/agents/codex.js +0 -213
- package/lib/agents/codex.ts +0 -238
- package/lib/agents/limit-hit.js +0 -259
- package/lib/agents/limit-hit.ts +0 -262
- package/lib/agents/mistral-telemetry.js +0 -140
- package/lib/agents/mistral-telemetry.ts +0 -159
- package/lib/agents/mistral.js +0 -174
- package/lib/agents/mistral.ts +0 -224
- package/lib/agents/opencode-export.js +0 -158
- package/lib/agents/opencode-export.ts +0 -160
- package/lib/agents/opencode-telemetry.js +0 -372
- package/lib/agents/opencode-telemetry.ts +0 -350
- package/lib/agents/opencode.js +0 -355
- package/lib/agents/opencode.ts +0 -372
- package/lib/agents/stage-telemetry.js +0 -41
- package/lib/agents/stage-telemetry.ts +0 -47
- package/lib/commands/active.js +0 -642
- package/lib/commands/active.ts +0 -707
- package/lib/commands/checkpoint.js +0 -102
- package/lib/commands/checkpoint.ts +0 -79
- package/lib/commands/config.js +0 -76
- package/lib/commands/config.ts +0 -52
- package/lib/commands/coverage-gate.js +0 -408
- package/lib/commands/coverage-gate.ts +0 -367
- package/lib/commands/diff.js +0 -151
- package/lib/commands/diff.ts +0 -130
- package/lib/commands/draft.js +0 -920
- package/lib/commands/draft.ts +0 -1026
- package/lib/commands/handoff.js +0 -685
- package/lib/commands/handoff.ts +0 -705
- package/lib/commands/integrate.js +0 -1612
- package/lib/commands/integrate.ts +0 -1724
- package/lib/commands/mission-start.js +0 -313
- package/lib/commands/mission-start.ts +0 -268
- package/lib/commands/rebase.js +0 -667
- package/lib/commands/rebase.ts +0 -639
- package/lib/commands/repair-handoff.js +0 -363
- package/lib/commands/repair-handoff.ts +0 -373
- package/lib/commands/resolve-conflict.js +0 -137
- package/lib/commands/resolve-conflict.ts +0 -117
- package/lib/commands/review.js +0 -18
- package/lib/commands/review.ts +0 -19
- package/lib/commands/setup-review.js +0 -18
- package/lib/commands/setup-review.ts +0 -19
- package/lib/commands/setup.js +0 -9
- package/lib/commands/setup.ts +0 -7
- package/lib/commands/stats-backfill.js +0 -448
- package/lib/commands/stats-backfill.ts +0 -423
- package/lib/commands/stats.js +0 -2016
- package/lib/commands/stats.ts +0 -2135
- package/lib/commands/status.js +0 -246
- package/lib/commands/status.ts +0 -224
- package/lib/commands/verify.js +0 -12
- package/lib/commands/verify.ts +0 -7
- package/lib/core/fmt.js +0 -178
- package/lib/core/fmt.ts +0 -189
- package/lib/core/git.js +0 -140
- package/lib/core/git.ts +0 -146
- package/lib/core/gitignore.js +0 -73
- package/lib/core/gitignore.ts +0 -108
- package/lib/core/mission-utils.js +0 -1058
- package/lib/core/mission-utils.ts +0 -998
- package/lib/core/nels.js +0 -184
- package/lib/core/nels.ts +0 -189
- package/lib/core/persistent-data-migration.js +0 -285
- package/lib/core/persistent-data-migration.ts +0 -257
- package/lib/core/product-config.js +0 -460
- package/lib/core/product-config.ts +0 -518
- package/lib/core/runtime-matrix.js +0 -49
- package/lib/core/runtime-matrix.ts +0 -84
- package/lib/core/spawn-tee.js +0 -160
- package/lib/core/spawn-tee.ts +0 -202
- package/lib/core/state-map.js +0 -108
- package/lib/core/state-map.ts +0 -115
- package/lib/core/storage.js +0 -151
- package/lib/core/storage.ts +0 -182
- package/lib/core/subagent-limit.js +0 -27
- package/lib/core/subagent-limit.ts +0 -25
- package/lib/core/verification.js +0 -176
- package/lib/core/verification.ts +0 -200
- package/lib/index.js +0 -160
- package/lib/index.ts +0 -134
- package/lib/review/rebase.js +0 -168
- package/lib/review/rebase.ts +0 -188
- package/lib/review/review-adapter.js +0 -234
- package/lib/review/review-adapter.ts +0 -198
- package/lib/review/review-artifacts.js +0 -542
- package/lib/review/review-artifacts.ts +0 -622
- package/lib/review/review-commands.js +0 -1318
- package/lib/review/review-commands.ts +0 -1579
- package/lib/review/review-events.js +0 -716
- package/lib/review/review-events.ts +0 -954
- package/lib/review/review-loop.js +0 -1271
- package/lib/review/review-loop.ts +0 -1493
- package/lib/review/review-polling.js +0 -132
- package/lib/review/review-polling.ts +0 -194
- package/lib/review/review-prompts.js +0 -212
- package/lib/review/review-prompts.ts +0 -186
- package/lib/review/review-state.js +0 -325
- package/lib/review/review-state.ts +0 -353
- package/lib/review/review.js +0 -126
- package/lib/review/review.ts +0 -143
- package/lib/tools/backlog.js +0 -848
- package/lib/tools/backlog.ts +0 -835
- package/lib/tools/forgejo.js +0 -1659
- package/lib/tools/forgejo.ts +0 -1793
- package/lib/tools/gatekeeper.js +0 -134
- package/lib/tools/gatekeeper.ts +0 -124
- package/lib/tools/redgreen.js +0 -239
- package/lib/tools/redgreen.ts +0 -221
- package/lib/tools/sessions.js +0 -87
- package/lib/tools/sessions.ts +0 -81
- package/lib/tools/setup-review.js +0 -1083
- package/lib/tools/setup-review.ts +0 -1152
- package/prompts/act-on-review-verbose.md +0 -20
- package/prompts/execute.md +0 -24
- package/prompts/portfolio.md +0 -30
- package/prompts/review-verbose.md +0 -36
- package/prompts/review.md +0 -50
- package/px.js +0 -268
- package/templates/AGENTS-snippet.md +0 -14
- package/templates/AGENTS.md.template +0 -34
- package/templates/CLAUDE.md.template +0 -27
- package/templates/CODEX.md.template +0 -38
- package/templates/MISTRAL.md.template +0 -24
- package/templates/claude-commands/act-on-review.md +0 -3
- package/templates/claude-commands/area-review.md +0 -3
- package/templates/claude-commands/draft.md +0 -6
- package/templates/claude-commands/execute.md +0 -6
- package/templates/claude-commands/integrate.md +0 -4
- package/templates/claude-commands/portfolio.md +0 -5
- package/templates/claude-commands/review.md +0 -4
- package/templates/codex/config.toml +0 -6
- package/templates/mission-scaffold.md +0 -39
- package/templates/vibe/skills/act-on-review/SKILL.md +0 -16
- package/templates/vibe/skills/area-review/SKILL.md +0 -16
- package/templates/vibe/skills/draft/SKILL.md +0 -16
- package/templates/vibe/skills/execute/SKILL.md +0 -16
- package/templates/vibe/skills/integrate/SKILL.md +0 -16
- package/templates/vibe/skills/portfolio/SKILL.md +0 -21
- package/templates/vibe/skills/review/SKILL.md +0 -16
- package/tools/setup-forgejo-docker.sh +0 -87
- /package/{config → build/config}/state-map.json +0 -0
- /package/{data/.gitkeep → build/prompts/draft.md} +0 -0
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* coverage-gate.js - run parallix tests with Node's built-in coverage support
|
|
5
|
-
* and enforce a configurable line-coverage threshold (default 90%).
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* node parallix/lib/commands/coverage-gate.js [--threshold <pct>] [--dry-run]
|
|
9
|
-
*
|
|
10
|
-
* Exit 0 when tests pass and coverage >= threshold.
|
|
11
|
-
* Exit 1 otherwise.
|
|
12
|
-
*
|
|
13
|
-
* Denominator: parallix/index.js plus all nested .js files under parallix/lib
|
|
14
|
-
* Excludes: parallix/test/*, parallix/prompts/*, parallix/config/*.json,
|
|
15
|
-
* coverage output dirs, node_modules, generated/temp files.
|
|
16
|
-
*
|
|
17
|
-
* /tmp write inventory (SC-1): every /tmp or os.tmpdir() write location used by
|
|
18
|
-
* coverage-gate.js and the workflow test infrastructure it runs:
|
|
19
|
-
*
|
|
20
|
-
* 1. PER_RUN_SCRATCH array (line 58) — tracks per-process scratch dirs created
|
|
21
|
-
* by this process. Each entry is a path returned by fs.mkdtempSync().
|
|
22
|
-
* 2. Node --experimental-test-coverage scratch (line 146) — Node creates
|
|
23
|
-
* coverage-*.json files under NODE_V8_COVERAGE. coverage-gate.js sets
|
|
24
|
-
* NODE_V8_COVERAGE to a per-process unique dir via createPerRunScratchDirs()
|
|
25
|
-
* (line 176), so Node writes to a unique path, never /tmp/node-coverage-*.
|
|
26
|
-
* 3. parallix/coverage/ directory (line 153) — created via fs.mkdirSync for
|
|
27
|
-
* lcov output; lives under REPO_ROOT, not /tmp.
|
|
28
|
-
* 4. TEMP_DIR_PREFIXES (lines 26-44) — prefix-based cleanup allowlist used by
|
|
29
|
-
* cleanupNewTempDirs() (lines 94-110). Covers dirs created by test files
|
|
30
|
-
* under parallix/test/*. These prefixes are intentionally NOT modified per SC-8.
|
|
31
|
-
* 5. os.tmpdir() default parameter (lines 85, 94) — listTempEntries() and
|
|
32
|
-
* cleanupNewTempDirs() accept os.tmpdir() as default root. runTests() passes
|
|
33
|
-
* a per-run TMPDIR to the child test process and cleans only that root.
|
|
34
|
-
* 6. Per-process mkdtempSync dirs (line 113) — createPerRunScratchDirs() creates
|
|
35
|
-
* a unique dir via fs.mkdtempSync(path.join(os.tmpdir(), 'node-coverage-'))
|
|
36
|
-
* and records it in PER_RUN_SCRATCH for targeted cleanup.
|
|
37
|
-
* 7. Test files (37 files, ~168 mkdtempSync calls) — all use
|
|
38
|
-
* fs.mkdtempSync(path.join(os.tmpdir(), 'prefix-')) pattern; already
|
|
39
|
-
* per-process unique. No fixed-path /tmp writes in test files. Generic
|
|
40
|
-
* runtime-* dirs are intentionally excluded because runtime-matrix launcher
|
|
41
|
-
* tests keep executable probes there while parallel coverage processes run.
|
|
42
|
-
* 8. /tmp/test-main — not produced by any in-scope code; orphaned 1.1 GB dir
|
|
43
|
-
* on disk from manual integration test (pre-existing, outside parallix/ scope).
|
|
44
|
-
* 9. Prompt templates (review.md, review-verbose.md, act-on-review.md, etc.) —
|
|
45
|
-
* /tmp/{{slug}}-*.md patterns are templates, not actual writes.
|
|
46
|
-
*
|
|
47
|
-
* Cleanup strategy: per-process inventory (PER_RUN_SCRATCH) + exit/SIGINT/SIGTERM
|
|
48
|
-
* handlers (lines 131-141) that remove only tracked dirs. No blanket rm -rf.
|
|
49
|
-
*/
|
|
50
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
51
|
-
if (k2 === undefined) k2 = k;
|
|
52
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
53
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
54
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
55
|
-
}
|
|
56
|
-
Object.defineProperty(o, k2, desc);
|
|
57
|
-
}) : (function(o, m, k, k2) {
|
|
58
|
-
if (k2 === undefined) k2 = k;
|
|
59
|
-
o[k2] = m[k];
|
|
60
|
-
}));
|
|
61
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
62
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
63
|
-
}) : function(o, v) {
|
|
64
|
-
o["default"] = v;
|
|
65
|
-
});
|
|
66
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
67
|
-
var ownKeys = function(o) {
|
|
68
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
69
|
-
var ar = [];
|
|
70
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
71
|
-
return ar;
|
|
72
|
-
};
|
|
73
|
-
return ownKeys(o);
|
|
74
|
-
};
|
|
75
|
-
return function (mod) {
|
|
76
|
-
if (mod && mod.__esModule) return mod;
|
|
77
|
-
var result = {};
|
|
78
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
79
|
-
__setModuleDefault(result, mod);
|
|
80
|
-
return result;
|
|
81
|
-
};
|
|
82
|
-
})();
|
|
83
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
84
|
-
exports.DEFAULT_TEST_TIMEOUT_MS = exports.COVERAGE_INCLUDES = exports.COVERAGE_EXCLUDES = void 0;
|
|
85
|
-
exports.run = run;
|
|
86
|
-
exports.cleanupPerRunScratch = cleanupPerRunScratch;
|
|
87
|
-
exports.createPerRunScratchDirs = createPerRunScratchDirs;
|
|
88
|
-
exports.discoverTestFiles = discoverTestFiles;
|
|
89
|
-
exports.listTempEntries = listTempEntries;
|
|
90
|
-
exports.registerExitHandlers = registerExitHandlers;
|
|
91
|
-
exports.resetPerRunScratchState = resetPerRunScratchState;
|
|
92
|
-
exports.resolveTestTimeoutMs = resolveTestTimeoutMs;
|
|
93
|
-
exports.runTests = runTests;
|
|
94
|
-
exports.shouldCleanTempDir = shouldCleanTempDir;
|
|
95
|
-
const node_child_process_1 = require("node:child_process");
|
|
96
|
-
const fs = __importStar(require("node:fs"));
|
|
97
|
-
const os = __importStar(require("node:os"));
|
|
98
|
-
const path = __importStar(require("node:path"));
|
|
99
|
-
const fmt = __importStar(require("../core/fmt.js"));
|
|
100
|
-
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
101
|
-
const SELF_TEST_FILE = 'coverage-gate.test.js';
|
|
102
|
-
const TEMP_DIR_PREFIXES = [
|
|
103
|
-
'agents-',
|
|
104
|
-
'sessions-',
|
|
105
|
-
'review-',
|
|
106
|
-
'forgejo-',
|
|
107
|
-
'workflow-',
|
|
108
|
-
'gatekeeper-',
|
|
109
|
-
'graphify-',
|
|
110
|
-
'claude-',
|
|
111
|
-
'codex-',
|
|
112
|
-
'gemini-',
|
|
113
|
-
'opencode-',
|
|
114
|
-
'startagent-',
|
|
115
|
-
'test-',
|
|
116
|
-
'mission-task-',
|
|
117
|
-
'visualBoard-task-',
|
|
118
|
-
'backlog-'
|
|
119
|
-
];
|
|
120
|
-
const COVERAGE_INCLUDES = [
|
|
121
|
-
'index.js',
|
|
122
|
-
'lib/**/*.js'
|
|
123
|
-
];
|
|
124
|
-
exports.COVERAGE_INCLUDES = COVERAGE_INCLUDES;
|
|
125
|
-
const COVERAGE_EXCLUDES = [
|
|
126
|
-
'test/**',
|
|
127
|
-
'prompts/**',
|
|
128
|
-
'config/*.json',
|
|
129
|
-
'.workflow/**',
|
|
130
|
-
'node_modules/**'
|
|
131
|
-
];
|
|
132
|
-
exports.COVERAGE_EXCLUDES = COVERAGE_EXCLUDES;
|
|
133
|
-
// The full suite regularly exceeds 10 minutes in this repository, especially
|
|
134
|
-
// under cold caches. Keep the gate generous so it can finish without a manual
|
|
135
|
-
// override while still failing on real hangs.
|
|
136
|
-
const DEFAULT_TEST_TIMEOUT_MS = 3_600_000;
|
|
137
|
-
exports.DEFAULT_TEST_TIMEOUT_MS = DEFAULT_TEST_TIMEOUT_MS;
|
|
138
|
-
const PER_RUN_SCRATCH = [];
|
|
139
|
-
let threshold = 90;
|
|
140
|
-
let dryRun = false;
|
|
141
|
-
let lcov = false;
|
|
142
|
-
let cleanupDone = false;
|
|
143
|
-
for (let i = 2; i < process.argv.length; i++) {
|
|
144
|
-
if (process.argv[i] === '--threshold' && process.argv[i + 1]) {
|
|
145
|
-
threshold = parseFloat(process.argv[i + 1]);
|
|
146
|
-
i++;
|
|
147
|
-
}
|
|
148
|
-
else if (process.argv[i] === '--dry-run') {
|
|
149
|
-
dryRun = true;
|
|
150
|
-
}
|
|
151
|
-
else if (process.argv[i] === '--lcov') {
|
|
152
|
-
lcov = true;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function discoverTestFiles() {
|
|
156
|
-
const testDir = path.join(REPO_ROOT, 'test');
|
|
157
|
-
if (!fs.existsSync(testDir)) {
|
|
158
|
-
return [];
|
|
159
|
-
}
|
|
160
|
-
return fs.readdirSync(testDir)
|
|
161
|
-
.filter(file => file.endsWith('.test.js'))
|
|
162
|
-
.filter(file => file !== SELF_TEST_FILE)
|
|
163
|
-
.map(file => path.join(testDir, file))
|
|
164
|
-
.sort();
|
|
165
|
-
}
|
|
166
|
-
function listTempEntries(tmpRoot = os.tmpdir()) {
|
|
167
|
-
if (!fs.existsSync(tmpRoot)) {
|
|
168
|
-
return new Set();
|
|
169
|
-
}
|
|
170
|
-
return new Set(fs.readdirSync(tmpRoot));
|
|
171
|
-
}
|
|
172
|
-
function shouldCleanTempDir(name) {
|
|
173
|
-
return TEMP_DIR_PREFIXES.some(prefix => name.startsWith(prefix));
|
|
174
|
-
}
|
|
175
|
-
function cleanupNewTempDirs(beforeEntries, tmpRoot = os.tmpdir()) {
|
|
176
|
-
if (!fs.existsSync(tmpRoot)) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
for (const name of fs.readdirSync(tmpRoot)) {
|
|
180
|
-
if (beforeEntries.has(name) || !shouldCleanTempDir(name)) {
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
const fullPath = path.join(tmpRoot, name);
|
|
184
|
-
let stat = null;
|
|
185
|
-
try {
|
|
186
|
-
stat = fs.statSync(fullPath);
|
|
187
|
-
}
|
|
188
|
-
catch (_) {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (!stat.isDirectory()) {
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
try {
|
|
195
|
-
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
196
|
-
}
|
|
197
|
-
catch (_) { }
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
function createPerRunScratchDirs() {
|
|
201
|
-
const coverageDir = fs.mkdtempSync(path.join(os.tmpdir(), 'node-coverage-'));
|
|
202
|
-
PER_RUN_SCRATCH.push(coverageDir);
|
|
203
|
-
return coverageDir;
|
|
204
|
-
}
|
|
205
|
-
function createPerRunTmpRoot() {
|
|
206
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'coverage-gate-tmp-'));
|
|
207
|
-
PER_RUN_SCRATCH.push(tmpRoot);
|
|
208
|
-
return tmpRoot;
|
|
209
|
-
}
|
|
210
|
-
function createMockGraphifyBin() {
|
|
211
|
-
const graphifyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'graphify-'));
|
|
212
|
-
PER_RUN_SCRATCH.push(graphifyDir);
|
|
213
|
-
const graphifyBin = path.join(graphifyDir, 'graphify');
|
|
214
|
-
fs.writeFileSync(graphifyBin, `#!/usr/bin/env bash
|
|
215
|
-
set -euo pipefail
|
|
216
|
-
if [[ "\${1:-}" == "--help" ]]; then
|
|
217
|
-
echo "mock graphify"
|
|
218
|
-
exit 0
|
|
219
|
-
fi
|
|
220
|
-
if [[ "\${1:-}" == "update" ]]; then
|
|
221
|
-
mkdir -p graphify-out
|
|
222
|
-
echo '{"nodes":[],"edges":[]}' > graphify-out/graph.json
|
|
223
|
-
echo '# Mock Graph Report' > graphify-out/GRAPH_REPORT.md
|
|
224
|
-
echo "[mock graphify] update $*"
|
|
225
|
-
exit 0
|
|
226
|
-
fi
|
|
227
|
-
echo "Unhandled graphify command: $*" >&2
|
|
228
|
-
exit 1
|
|
229
|
-
`, { mode: 0o755 });
|
|
230
|
-
return graphifyBin;
|
|
231
|
-
}
|
|
232
|
-
function cleanupPerRunScratch() {
|
|
233
|
-
if (cleanupDone) {
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
cleanupDone = true;
|
|
237
|
-
for (const dir of PER_RUN_SCRATCH) {
|
|
238
|
-
try {
|
|
239
|
-
if (fs.existsSync(dir)) {
|
|
240
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
catch (_) { }
|
|
244
|
-
}
|
|
245
|
-
PER_RUN_SCRATCH.length = 0;
|
|
246
|
-
}
|
|
247
|
-
function registerExitHandlers() {
|
|
248
|
-
process.on('exit', cleanupPerRunScratch);
|
|
249
|
-
process.on('SIGINT', () => {
|
|
250
|
-
cleanupPerRunScratch();
|
|
251
|
-
process.exit(130);
|
|
252
|
-
});
|
|
253
|
-
process.on('SIGTERM', () => {
|
|
254
|
-
cleanupPerRunScratch();
|
|
255
|
-
process.exit(143);
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
function resetPerRunScratchState() {
|
|
259
|
-
PER_RUN_SCRATCH.length = 0;
|
|
260
|
-
cleanupDone = false;
|
|
261
|
-
}
|
|
262
|
-
function buildCoverageArgs(testFiles, coverageThreshold = threshold, useLcov = lcov) {
|
|
263
|
-
const args = [
|
|
264
|
-
'--test',
|
|
265
|
-
'--experimental-test-coverage',
|
|
266
|
-
`--test-coverage-lines=${coverageThreshold}`,
|
|
267
|
-
...COVERAGE_INCLUDES.flatMap(pattern => ['--test-coverage-include', pattern]),
|
|
268
|
-
...COVERAGE_EXCLUDES.flatMap(pattern => ['--test-coverage-exclude', pattern]),
|
|
269
|
-
];
|
|
270
|
-
if (useLcov) {
|
|
271
|
-
const coverageDir = path.join(REPO_ROOT, 'coverage');
|
|
272
|
-
if (!fs.existsSync(coverageDir)) {
|
|
273
|
-
fs.mkdirSync(coverageDir, { recursive: true });
|
|
274
|
-
}
|
|
275
|
-
args.push('--test-reporter=lcov');
|
|
276
|
-
args.push(`--test-reporter-destination=${path.join(coverageDir, 'lcov.info')}`);
|
|
277
|
-
args.push('--test-reporter=spec');
|
|
278
|
-
args.push('--test-reporter-destination=stdout');
|
|
279
|
-
}
|
|
280
|
-
args.push(...testFiles);
|
|
281
|
-
return args;
|
|
282
|
-
}
|
|
283
|
-
function resolveTestTimeoutMs(env = process.env) {
|
|
284
|
-
const raw = env.WORKFLOW_COVERAGE_GATE_TIMEOUT_MS;
|
|
285
|
-
if (raw === undefined || raw === '') {
|
|
286
|
-
return DEFAULT_TEST_TIMEOUT_MS;
|
|
287
|
-
}
|
|
288
|
-
const parsed = Number(raw);
|
|
289
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_TEST_TIMEOUT_MS;
|
|
290
|
-
}
|
|
291
|
-
function runTests(testFiles, coverageThreshold = threshold, _spawnSync = node_child_process_1.spawnSync) {
|
|
292
|
-
const tmpRoot = createPerRunTmpRoot();
|
|
293
|
-
const tmpEntriesBefore = listTempEntries(tmpRoot);
|
|
294
|
-
const nodeCoverageDir = createPerRunScratchDirs();
|
|
295
|
-
const childEnv = { ...process.env };
|
|
296
|
-
delete childEnv.NODE_TEST_CONTEXT;
|
|
297
|
-
delete childEnv.NODE_OPTIONS;
|
|
298
|
-
childEnv.TMPDIR = tmpRoot;
|
|
299
|
-
childEnv.NODE_V8_COVERAGE = nodeCoverageDir;
|
|
300
|
-
childEnv.GRAPHIFY_BIN = createMockGraphifyBin();
|
|
301
|
-
const result = _spawnSync(process.execPath, buildCoverageArgs(testFiles, coverageThreshold), {
|
|
302
|
-
encoding: 'utf8',
|
|
303
|
-
cwd: REPO_ROOT,
|
|
304
|
-
env: childEnv,
|
|
305
|
-
stdio: ['pipe', 'inherit', 'inherit'],
|
|
306
|
-
timeout: resolveTestTimeoutMs(),
|
|
307
|
-
});
|
|
308
|
-
cleanupNewTempDirs(tmpEntriesBefore, tmpRoot);
|
|
309
|
-
cleanupPerRunScratch();
|
|
310
|
-
if (result.error) {
|
|
311
|
-
fmt.log.error(`[coverage-gate] failed to spawn test runner: ${result.error.message}`);
|
|
312
|
-
return 1;
|
|
313
|
-
}
|
|
314
|
-
if (result.signal) {
|
|
315
|
-
fmt.log.error(`[coverage-gate] test runner killed by signal ${result.signal}`);
|
|
316
|
-
return 1;
|
|
317
|
-
}
|
|
318
|
-
return result.status === null ? 1 : result.status;
|
|
319
|
-
}
|
|
320
|
-
function main() {
|
|
321
|
-
const testFiles = discoverTestFiles();
|
|
322
|
-
if (testFiles.length === 0) {
|
|
323
|
-
fmt.log.fail('no parallix test files found under test/');
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
327
|
-
if (dryRun) {
|
|
328
|
-
fmt.log.info(`DRY-RUN mode — threshold=${threshold}%`);
|
|
329
|
-
fmt.log.info('Denominator: index.js + lib/**/*.js');
|
|
330
|
-
fmt.log.info(`Include globs: ${COVERAGE_INCLUDES.join(', ')}`);
|
|
331
|
-
fmt.log.info(`Exclude globs: ${COVERAGE_EXCLUDES.join(', ')}`);
|
|
332
|
-
fmt.log.info(`Would run: ${fmt.command(`${process.execPath} ${buildCoverageArgs(testFiles, threshold).join(' ')}`)}`);
|
|
333
|
-
process.exit(0);
|
|
334
|
-
}
|
|
335
|
-
registerExitHandlers();
|
|
336
|
-
process.exit(runTests(testFiles, threshold));
|
|
337
|
-
}
|
|
338
|
-
if (typeof require !== 'undefined' && require.main === module) {
|
|
339
|
-
main();
|
|
340
|
-
}
|
|
341
|
-
function run(args, options = {}) {
|
|
342
|
-
const exitFn = options.exitFn || process.exit;
|
|
343
|
-
let threshold_ = 90;
|
|
344
|
-
let dryRun_ = false;
|
|
345
|
-
for (let i = 0; i < args.length; i++) {
|
|
346
|
-
if (args[i] === '--threshold' && args[i + 1]) {
|
|
347
|
-
threshold_ = parseFloat(args[i + 1]);
|
|
348
|
-
i++;
|
|
349
|
-
}
|
|
350
|
-
else if (args[i] === '--dry-run') {
|
|
351
|
-
dryRun_ = true;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
const savedThreshold = threshold;
|
|
355
|
-
const savedDryRun = dryRun;
|
|
356
|
-
threshold = threshold_;
|
|
357
|
-
dryRun = dryRun_;
|
|
358
|
-
try {
|
|
359
|
-
if (dryRun_) {
|
|
360
|
-
const testFiles = discoverTestFiles();
|
|
361
|
-
if (testFiles.length === 0) {
|
|
362
|
-
if (typeof exitFn === 'function') {
|
|
363
|
-
exitFn(1);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
fmt.log.info(`Found ${testFiles.length} test file(s)`);
|
|
368
|
-
fmt.log.info(`DRY-RUN mode — threshold=${threshold}%`);
|
|
369
|
-
fmt.log.info('Denominator: index.js + lib/**/*.js');
|
|
370
|
-
fmt.log.info(`Include globs: ${COVERAGE_INCLUDES.join(', ')}`);
|
|
371
|
-
fmt.log.info(`Exclude globs: ${COVERAGE_EXCLUDES.join(', ')}`);
|
|
372
|
-
fmt.log.info(`Would run: ${fmt.command(`${process.execPath} ${buildCoverageArgs(testFiles, threshold).join(' ')}`)}`);
|
|
373
|
-
if (typeof exitFn === 'function') {
|
|
374
|
-
exitFn(0);
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
process.exit(0);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
registerExitHandlers();
|
|
383
|
-
exitFn(runTests(discoverTestFiles(), threshold));
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
finally {
|
|
387
|
-
threshold = savedThreshold;
|
|
388
|
-
dryRun = savedDryRun;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
run.buildCoverageArgs = buildCoverageArgs;
|
|
392
|
-
run.cleanupNewTempDirs = cleanupNewTempDirs;
|
|
393
|
-
run.cleanupPerRunScratch = cleanupPerRunScratch;
|
|
394
|
-
run.createPerRunScratchDirs = createPerRunScratchDirs;
|
|
395
|
-
run.COVERAGE_EXCLUDES = COVERAGE_EXCLUDES;
|
|
396
|
-
run.COVERAGE_INCLUDES = COVERAGE_INCLUDES;
|
|
397
|
-
run.DEFAULT_TEST_TIMEOUT_MS = DEFAULT_TEST_TIMEOUT_MS;
|
|
398
|
-
run.discoverTestFiles = discoverTestFiles;
|
|
399
|
-
run.listTempEntries = listTempEntries;
|
|
400
|
-
run.registerExitHandlers = registerExitHandlers;
|
|
401
|
-
run.resetPerRunScratchState = resetPerRunScratchState;
|
|
402
|
-
run.resolveTestTimeoutMs = resolveTestTimeoutMs;
|
|
403
|
-
run.runTests = runTests;
|
|
404
|
-
run.shouldCleanTempDir = shouldCleanTempDir;
|
|
405
|
-
exports.default = run;
|
|
406
|
-
if (typeof module !== 'undefined') {
|
|
407
|
-
module.exports = run;
|
|
408
|
-
}
|