@lsctech/polaris 0.1.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/README.md +87 -0
- package/dist/__mocks__/tool-server-linear.js +34 -0
- package/dist/cli/adopt-approve.js +60 -0
- package/dist/cli/adopt-cognition.js +199 -0
- package/dist/cli/adopt-instructions.js +143 -0
- package/dist/cli/adopt-rules.js +169 -0
- package/dist/cli/adopt-scan.js +25 -0
- package/dist/cli/adopt-smartdocs.js +192 -0
- package/dist/cli/adoption-inventory.js +350 -0
- package/dist/cli/adoption-plan.js +222 -0
- package/dist/cli/args.js +28 -0
- package/dist/cli/args.test.js +30 -0
- package/dist/cli/branding.js +41 -0
- package/dist/cli/graph.js +358 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/index.test.js +162 -0
- package/dist/cli/init-detect.js +61 -0
- package/dist/cli/init.js +492 -0
- package/dist/cli/init.test.js +259 -0
- package/dist/cli/librarian.js +32 -0
- package/dist/cli/medic.js +96 -0
- package/dist/cli/startup.test.js +23 -0
- package/dist/cli/tracker.js +130 -0
- package/dist/cli/tracker.test.js +126 -0
- package/dist/cli/version.js +10 -0
- package/dist/cli/version.test.js +11 -0
- package/dist/cli/worker.js +287 -0
- package/dist/cluster-state/fixtures/test-clusters.json +19 -0
- package/dist/cluster-state/store.js +302 -0
- package/dist/cluster-state/store.test.js +145 -0
- package/dist/cluster-state/types.js +2 -0
- package/dist/cognition/archive.js +158 -0
- package/dist/cognition/closeout-librarian-types.js +161 -0
- package/dist/cognition/cognition.test.js +623 -0
- package/dist/cognition/index.js +41 -0
- package/dist/cognition/librarian-dispatch.js +391 -0
- package/dist/cognition/librarian-dispatch.test.js +247 -0
- package/dist/cognition/librarian-packet.js +313 -0
- package/dist/cognition/librarian-types.js +57 -0
- package/dist/cognition/route-cognition-delta.js +350 -0
- package/dist/cognition/summary-delta.js +279 -0
- package/dist/cognition/validate.js +162 -0
- package/dist/config/defaults.js +98 -0
- package/dist/config/doctor.js +273 -0
- package/dist/config/index.js +14 -0
- package/dist/config/loader.js +58 -0
- package/dist/config/provider-detect.js +60 -0
- package/dist/config/provider-detect.test.js +119 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/show.js +44 -0
- package/dist/config/show.test.js +42 -0
- package/dist/config/validator.js +675 -0
- package/dist/config/validator.test.js +77 -0
- package/dist/docs/canon-check.js +334 -0
- package/dist/docs/canon-check.test.js +207 -0
- package/dist/docs/doctrine.js +133 -0
- package/dist/docs/doctrine.test.js +139 -0
- package/dist/docs/index.js +168 -0
- package/dist/docs/index.test.js +83 -0
- package/dist/docs/ingest.js +295 -0
- package/dist/docs/ingest.test.js +71 -0
- package/dist/docs/migrate.js +165 -0
- package/dist/docs/migrate.test.js +136 -0
- package/dist/docs/seed-instructions.js +147 -0
- package/dist/docs/seed-instructions.test.js +137 -0
- package/dist/docs/validate-instructions.js +267 -0
- package/dist/docs/validate-instructions.test.js +238 -0
- package/dist/finalize/artifact-policy.js +214 -0
- package/dist/finalize/artifact-policy.test.js +84 -0
- package/dist/finalize/delivery-integrity.js +141 -0
- package/dist/finalize/finalize.test.js +210 -0
- package/dist/finalize/github.js +41 -0
- package/dist/finalize/index.js +474 -0
- package/dist/finalize/linear.js +213 -0
- package/dist/finalize/run-report.js +47 -0
- package/dist/finalize/steps/01-map-update.js +11 -0
- package/dist/finalize/steps/02-map-validate.js +11 -0
- package/dist/finalize/steps/03-schema-validate.js +11 -0
- package/dist/finalize/steps/04-run-checks.js +118 -0
- package/dist/finalize/steps/05-generate-report.js +14 -0
- package/dist/finalize/steps/06-commit.js +39 -0
- package/dist/finalize/steps/07-push.js +10 -0
- package/dist/finalize/steps/08-create-pr.js +9 -0
- package/dist/finalize/steps/09-update-state.js +9 -0
- package/dist/finalize/steps/10-append-jsonl.js +23 -0
- package/dist/finalize/steps/11-update-linear.js +22 -0
- package/dist/finalize/steps/12-archive.js +21 -0
- package/dist/graph/adapter/c/adapter.js +45 -0
- package/dist/graph/adapter/c/extract.js +135 -0
- package/dist/graph/adapter/c/index.js +10 -0
- package/dist/graph/adapter/c/runtime.js +67 -0
- package/dist/graph/adapter/cpp/adapter.js +45 -0
- package/dist/graph/adapter/cpp/extract.js +159 -0
- package/dist/graph/adapter/cpp/index.js +10 -0
- package/dist/graph/adapter/cpp/runtime.js +61 -0
- package/dist/graph/adapter/csharp/adapter.js +45 -0
- package/dist/graph/adapter/csharp/extract.js +127 -0
- package/dist/graph/adapter/csharp/index.js +10 -0
- package/dist/graph/adapter/csharp/runtime.js +61 -0
- package/dist/graph/adapter/dart/adapter.js +56 -0
- package/dist/graph/adapter/dart/extract.js +130 -0
- package/dist/graph/adapter/dart/index.js +10 -0
- package/dist/graph/adapter/dart/runtime.js +61 -0
- package/dist/graph/adapter/go/adapter.js +45 -0
- package/dist/graph/adapter/go/extract.js +112 -0
- package/dist/graph/adapter/go/index.js +10 -0
- package/dist/graph/adapter/go/runtime.js +58 -0
- package/dist/graph/adapter/kotlin-java/extract-common.js +83 -0
- package/dist/graph/adapter/kotlin-java/index.js +15 -0
- package/dist/graph/adapter/kotlin-java/java-adapter.js +45 -0
- package/dist/graph/adapter/kotlin-java/java-extract.js +42 -0
- package/dist/graph/adapter/kotlin-java/kotlin-adapter.js +48 -0
- package/dist/graph/adapter/kotlin-java/kotlin-extract.js +58 -0
- package/dist/graph/adapter/kotlin-java/runtime.js +75 -0
- package/dist/graph/adapter/python/adapter.js +45 -0
- package/dist/graph/adapter/python/extract.js +121 -0
- package/dist/graph/adapter/python/index.js +10 -0
- package/dist/graph/adapter/python/runtime.js +70 -0
- package/dist/graph/adapter/registry.js +82 -0
- package/dist/graph/adapter/rust/adapter.js +45 -0
- package/dist/graph/adapter/rust/extract.js +110 -0
- package/dist/graph/adapter/rust/index.js +10 -0
- package/dist/graph/adapter/rust/runtime.js +74 -0
- package/dist/graph/adapter/shell/adapter.js +34 -0
- package/dist/graph/adapter/shell/extract.js +98 -0
- package/dist/graph/adapter/shell/index.js +8 -0
- package/dist/graph/adapter/svelte/adapter.js +91 -0
- package/dist/graph/adapter/svelte/extract.js +41 -0
- package/dist/graph/adapter/svelte/index.js +8 -0
- package/dist/graph/adapter/swift/adapter.js +45 -0
- package/dist/graph/adapter/swift/extract.js +120 -0
- package/dist/graph/adapter/swift/index.js +10 -0
- package/dist/graph/adapter/swift/runtime.js +70 -0
- package/dist/graph/adapter/types.js +2 -0
- package/dist/graph/adapter/typescript-javascript/adapter.js +72 -0
- package/dist/graph/adapter/typescript-javascript/extract.js +115 -0
- package/dist/graph/adapter/typescript-javascript/index.js +10 -0
- package/dist/graph/adapter/typescript-javascript/runtime.js +97 -0
- package/dist/graph/capability/index.js +105 -0
- package/dist/graph/governance.js +104 -0
- package/dist/graph/parser/extract.js +5 -0
- package/dist/graph/parser/loader.js +2 -0
- package/dist/graph/parser/pipeline.js +194 -0
- package/dist/graph/query/index.js +277 -0
- package/dist/graph/query/types.js +5 -0
- package/dist/graph/resolver/build-edges.js +211 -0
- package/dist/graph/resolver/index.js +23 -0
- package/dist/graph/resolver/resolve-imports.js +168 -0
- package/dist/graph/store/adapter.js +132 -0
- package/dist/graph/store/queries.js +124 -0
- package/dist/graph/store/types.js +4 -0
- package/dist/ignore/defaults.js +41 -0
- package/dist/ignore/parser.js +39 -0
- package/dist/lint/map-reference-validator.js +72 -0
- package/dist/loop/abort.js +188 -0
- package/dist/loop/abort.test.js +151 -0
- package/dist/loop/adapters/__tests__/terminal-cli.test.js +92 -0
- package/dist/loop/adapters/agent-subtask.js +137 -0
- package/dist/loop/adapters/agent-subtask.test.js +151 -0
- package/dist/loop/adapters/cli-subtask-bridge.js +108 -0
- package/dist/loop/adapters/index.js +9 -0
- package/dist/loop/adapters/registry.js +17 -0
- package/dist/loop/adapters/terminal-cli.js +403 -0
- package/dist/loop/adapters/types.js +2 -0
- package/dist/loop/adapters/worker-instructions.js +85 -0
- package/dist/loop/body-parser.js +226 -0
- package/dist/loop/bootstrap-packet.js +97 -0
- package/dist/loop/bootstrap-packet.test.js +171 -0
- package/dist/loop/branch-governance.js +54 -0
- package/dist/loop/budget.js +63 -0
- package/dist/loop/budget.test.js +163 -0
- package/dist/loop/checkpoint.js +325 -0
- package/dist/loop/compact-return.js +59 -0
- package/dist/loop/continue.js +645 -0
- package/dist/loop/continue.test.js +337 -0
- package/dist/loop/dispatch-boundary.js +335 -0
- package/dist/loop/dispatch-state.js +223 -0
- package/dist/loop/dispatch-state.test.js +186 -0
- package/dist/loop/dispatch.js +1236 -0
- package/dist/loop/dispatch.test.js +499 -0
- package/dist/loop/ephemeral-smoke.test.js +160 -0
- package/dist/loop/evidence-backfill.js +216 -0
- package/dist/loop/execution-adapter.js +141 -0
- package/dist/loop/execution-adapter.test.js +66 -0
- package/dist/loop/finalize-evidence.js +169 -0
- package/dist/loop/git-custody.js +250 -0
- package/dist/loop/impl-packet-input.js +38 -0
- package/dist/loop/index.js +270 -0
- package/dist/loop/ledger.js +49 -0
- package/dist/loop/ledger.test.js +127 -0
- package/dist/loop/lifecycle-dispatch.js +348 -0
- package/dist/loop/lifecycle-dispatch.test.js +318 -0
- package/dist/loop/lifecycle.js +93 -0
- package/dist/loop/lifecycle.test.js +150 -0
- package/dist/loop/orphan-recovery.js +276 -0
- package/dist/loop/orphan-recovery.test.js +236 -0
- package/dist/loop/parent.js +1566 -0
- package/dist/loop/parent.test.js +738 -0
- package/dist/loop/provider-sealed-packet.test.js +164 -0
- package/dist/loop/resume.js +295 -0
- package/dist/loop/resume.test.js +172 -0
- package/dist/loop/run-bootstrap.js +234 -0
- package/dist/loop/run-preflight.js +203 -0
- package/dist/loop/status.js +665 -0
- package/dist/loop/status.test.js +235 -0
- package/dist/loop/wait.js +86 -0
- package/dist/loop/worker-packet.js +406 -0
- package/dist/loop/worker-packet.test.js +243 -0
- package/dist/loop/worker-prompt.js +260 -0
- package/dist/loop/worker-prompt.test.js +247 -0
- package/dist/loop/worker.js +498 -0
- package/dist/loop/worker.test.js +372 -0
- package/dist/map/atlas.js +77 -0
- package/dist/map/backfill.js +171 -0
- package/dist/map/backfill.test.js +120 -0
- package/dist/map/index.js +255 -0
- package/dist/map/inference.js +73 -0
- package/dist/map/inference.test.js +35 -0
- package/dist/map/query.js +157 -0
- package/dist/map/query.test.js +174 -0
- package/dist/map/update.js +355 -0
- package/dist/map/update.test.js +67 -0
- package/dist/map/validate.js +153 -0
- package/dist/map/validate.test.js +90 -0
- package/dist/map/welfare.js +86 -0
- package/dist/mcp/lib/invoke.js +35 -0
- package/dist/mcp/lib/redact.js +24 -0
- package/dist/mcp/lib/redact.test.js +112 -0
- package/dist/mcp/lib/root.js +41 -0
- package/dist/mcp/lib/root.test.js +114 -0
- package/dist/mcp/server.js +15 -0
- package/dist/mcp/tools/claim-child.js +119 -0
- package/dist/mcp/tools/claim-child.test.js +69 -0
- package/dist/mcp/tools/current-state.js +73 -0
- package/dist/mcp/tools/current-state.test.js +114 -0
- package/dist/mcp/tools/dispatch-result.js +186 -0
- package/dist/mcp/tools/dispatch-result.test.js +109 -0
- package/dist/mcp/tools/index.js +222 -0
- package/dist/mcp/tools/index.test.js +172 -0
- package/dist/mcp/tools/linear.js +74 -0
- package/dist/mcp/tools/loop-continue.js +159 -0
- package/dist/mcp/tools/loop-continue.test.js +186 -0
- package/dist/mcp/tools/loop-dry-run.js +15 -0
- package/dist/mcp/tools/status.js +65 -0
- package/dist/medic/chart-id.js +75 -0
- package/dist/medic/chart-schema.js +139 -0
- package/dist/runs/index.js +119 -0
- package/dist/runs/index.test.js +184 -0
- package/dist/runs/ledger-tail.js +15 -0
- package/dist/runs/list.js +29 -0
- package/dist/runs/reconcile.js +74 -0
- package/dist/runs/show.js +10 -0
- package/dist/runtime/audit/logger.js +15 -0
- package/dist/runtime/audit/reader.js +42 -0
- package/dist/runtime/checkpoint.js +89 -0
- package/dist/runtime/continuation/confirmed.js +225 -0
- package/dist/runtime/continuation/confirmed.test.js +421 -0
- package/dist/runtime/continuation/dry-run.js +74 -0
- package/dist/runtime/execution-window.js +106 -0
- package/dist/runtime/scheduling/child-selector.js +16 -0
- package/dist/runtime/state.js +43 -0
- package/dist/runtime/status.js +46 -0
- package/dist/runtime/verification/envelope.js +80 -0
- package/dist/runtime/verification/fingerprint.js +26 -0
- package/dist/skill-packet/cli.test.js +105 -0
- package/dist/skill-packet/generator.js +225 -0
- package/dist/skill-packet/generator.test.js +159 -0
- package/dist/skill-packet/index.js +49 -0
- package/dist/skill-packet/types.js +2 -0
- package/dist/smartdocs-engine/audit.js +194 -0
- package/dist/smartdocs-engine/audit.test.js +122 -0
- package/dist/smartdocs-engine/canon-check.js +340 -0
- package/dist/smartdocs-engine/canon-check.test.js +234 -0
- package/dist/smartdocs-engine/doctrine.js +633 -0
- package/dist/smartdocs-engine/doctrine.test.js +374 -0
- package/dist/smartdocs-engine/index.js +456 -0
- package/dist/smartdocs-engine/index.test.js +82 -0
- package/dist/smartdocs-engine/ingest.js +495 -0
- package/dist/smartdocs-engine/ingest.test.js +163 -0
- package/dist/smartdocs-engine/migrate.js +217 -0
- package/dist/smartdocs-engine/migrate.test.js +200 -0
- package/dist/smartdocs-engine/seed-instructions.js +335 -0
- package/dist/smartdocs-engine/seed-instructions.test.js +275 -0
- package/dist/smartdocs-engine/smartdoc-ignore.js +258 -0
- package/dist/smartdocs-engine/smartdoc-ignore.test.js +146 -0
- package/dist/smartdocs-engine/validate-instructions.js +366 -0
- package/dist/smartdocs-engine/validate-instructions.test.js +283 -0
- package/dist/tracker/adapters/github/index.js +305 -0
- package/dist/tracker/adapters/jira/index.js +293 -0
- package/dist/tracker/adapters/linear/http-errors.test.js +51 -0
- package/dist/tracker/adapters/linear/index.js +621 -0
- package/dist/tracker/adapters/linear/index.test.js +238 -0
- package/dist/tracker/adapters/linear.js +50 -0
- package/dist/tracker/adapters/local/index.js +10 -0
- package/dist/tracker/adapters/local-file/index.js +159 -0
- package/dist/tracker/adapters/mcp-bridge.js +158 -0
- package/dist/tracker/adapters/mcp-bridge.test.js +12 -0
- package/dist/tracker/adapters/spec/index.js +146 -0
- package/dist/tracker/capabilities.js +2 -0
- package/dist/tracker/index.js +49 -0
- package/dist/tracker/lifecycle-policy.js +139 -0
- package/dist/tracker/lifecycle-transition.js +164 -0
- package/dist/tracker/local-graph.js +98 -0
- package/dist/tracker/migration.js +56 -0
- package/dist/tracker/schema.js +86 -0
- package/dist/tracker/sync/index.js +404 -0
- package/dist/tracker/sync/queue-store.js +95 -0
- package/dist/tracker/sync/queue-store.test.js +104 -0
- package/dist/tracker/types.js +11 -0
- package/dist/types/linear.js +3 -0
- package/dist/types/result-packet.js +12 -0
- package/dist/types/runtime-state.js +2 -0
- package/dist/types/work-contract.js +2 -0
- package/dist/utils/monotonic-timestamp.js +13 -0
- package/dist/utils/monotonic-timestamp.test.js +19 -0
- package/package.json +64 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runFinalize = runFinalize;
|
|
4
|
+
exports.createFinalizeCommand = createFinalizeCommand;
|
|
5
|
+
const commander_1 = require("commander");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const closeout_librarian_types_js_1 = require("../cognition/closeout-librarian-types.js");
|
|
10
|
+
const loader_js_1 = require("../config/loader.js");
|
|
11
|
+
const checkpoint_js_1 = require("../loop/checkpoint.js");
|
|
12
|
+
const artifact_policy_js_1 = require("./artifact-policy.js");
|
|
13
|
+
const git_custody_js_1 = require("../loop/git-custody.js");
|
|
14
|
+
const store_js_1 = require("../cluster-state/store.js");
|
|
15
|
+
const canon_check_js_1 = require("../smartdocs-engine/canon-check.js");
|
|
16
|
+
const _01_map_update_js_1 = require("./steps/01-map-update.js");
|
|
17
|
+
const _02_map_validate_js_1 = require("./steps/02-map-validate.js");
|
|
18
|
+
const _03_schema_validate_js_1 = require("./steps/03-schema-validate.js");
|
|
19
|
+
const _04_run_checks_js_1 = require("./steps/04-run-checks.js");
|
|
20
|
+
const _05_generate_report_js_1 = require("./steps/05-generate-report.js");
|
|
21
|
+
const _06_commit_js_1 = require("./steps/06-commit.js");
|
|
22
|
+
const _07_push_js_1 = require("./steps/07-push.js");
|
|
23
|
+
const _08_create_pr_js_1 = require("./steps/08-create-pr.js");
|
|
24
|
+
const _09_update_state_js_1 = require("./steps/09-update-state.js");
|
|
25
|
+
const _10_append_jsonl_js_1 = require("./steps/10-append-jsonl.js");
|
|
26
|
+
const _11_update_linear_js_1 = require("./steps/11-update-linear.js");
|
|
27
|
+
const _12_archive_js_1 = require("./steps/12-archive.js");
|
|
28
|
+
const local_graph_js_1 = require("../tracker/local-graph.js");
|
|
29
|
+
const index_js_1 = require("../tracker/sync/index.js");
|
|
30
|
+
const finalize_evidence_js_1 = require("../loop/finalize-evidence.js");
|
|
31
|
+
const delivery_integrity_js_1 = require("./delivery-integrity.js");
|
|
32
|
+
function getBranch(repoRoot) {
|
|
33
|
+
try {
|
|
34
|
+
return (0, node_child_process_1.execFileSync)("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
35
|
+
cwd: repoRoot,
|
|
36
|
+
encoding: "utf-8",
|
|
37
|
+
}).trim();
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
41
|
+
throw new Error(`Failed to get current branch in ${repoRoot}: ${msg}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function normalizeBranchName(branch) {
|
|
45
|
+
return branch.toLowerCase().replace(/_/g, "-");
|
|
46
|
+
}
|
|
47
|
+
function extractClusterSlug(clusterId) {
|
|
48
|
+
const match = clusterId.match(/([A-Z]+-\d+)/);
|
|
49
|
+
return match ? normalizeBranchName(match[1]) : normalizeBranchName(clusterId);
|
|
50
|
+
}
|
|
51
|
+
function validateStateFilePath(stateFile) {
|
|
52
|
+
const normalizedPath = stateFile.replace(/\\/g, "/");
|
|
53
|
+
const debugPath = ".taskchain_artifacts/polaris-run/current-state.json";
|
|
54
|
+
const legacyPath = ".polaris/runs/current-state.json";
|
|
55
|
+
if (normalizedPath.endsWith(debugPath)) {
|
|
56
|
+
process.stderr.write(`finalize aborted: state file at compatibility/debug path — ${stateFile}\n` +
|
|
57
|
+
`Canonical state files must be at .polaris/clusters/<cluster-id>/state.json or custom path.\n`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
if (normalizedPath.endsWith(legacyPath)) {
|
|
61
|
+
process.stderr.write(`finalize aborted: state file at legacy path — ${stateFile}\n` +
|
|
62
|
+
`Canonical state files must be at .polaris/clusters/<cluster-id>/state.json or custom path.\n`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function validateClusterIdMatchesBranch(clusterId, branch) {
|
|
67
|
+
const clusterSlug = extractClusterSlug(clusterId);
|
|
68
|
+
const normalizedBranch = normalizeBranchName(branch);
|
|
69
|
+
const slugPattern = new RegExp(`(^|-)${clusterSlug.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(-|$)`);
|
|
70
|
+
if (!slugPattern.test(normalizedBranch)) {
|
|
71
|
+
process.stderr.write(`finalize aborted: cluster_id mismatch — state.cluster_id "${clusterId}" ` +
|
|
72
|
+
`does not match current branch "${branch}".\n` +
|
|
73
|
+
`Expected branch to contain slug "${clusterSlug}" (normalized from "${clusterId}").\n`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function validateStateBranchMatchesGitBranch(stateBranch, branch) {
|
|
78
|
+
if (!stateBranch || stateBranch.trim() === "") {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (stateBranch !== branch) {
|
|
82
|
+
process.stderr.write(`finalize aborted: state.branch mismatch — state.branch "${stateBranch}" ` +
|
|
83
|
+
`does not match current git branch "${branch}".\n`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check that the Closeout Librarian has run and its result passes the gate.
|
|
89
|
+
* Returns null if finalize may proceed; returns a human-readable blocker string if not.
|
|
90
|
+
*/
|
|
91
|
+
function checkLibrarianGate(repoRoot, clusterId) {
|
|
92
|
+
const packetsDir = (0, node_path_1.join)(repoRoot, ".polaris", "clusters", clusterId, "packets");
|
|
93
|
+
let packetFiles = [];
|
|
94
|
+
try {
|
|
95
|
+
packetFiles = (0, node_fs_1.readdirSync)(packetsDir)
|
|
96
|
+
.filter((f) => f.startsWith("librarian-packet-") && f.endsWith(".json"))
|
|
97
|
+
.sort();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// directory absent — no packet has been generated
|
|
101
|
+
}
|
|
102
|
+
const latestPacket = packetFiles
|
|
103
|
+
.map((file) => (0, node_path_1.join)(packetsDir, file))
|
|
104
|
+
.sort((a, b) => {
|
|
105
|
+
try {
|
|
106
|
+
return (0, node_fs_1.statSync)(b).mtimeMs - (0, node_fs_1.statSync)(a).mtimeMs;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return b.localeCompare(a);
|
|
110
|
+
}
|
|
111
|
+
})[0];
|
|
112
|
+
if (!latestPacket) {
|
|
113
|
+
return ("Closeout Librarian has not been dispatched for this cluster.\n" +
|
|
114
|
+
` 1. Generate packet: npm run polaris -- librarian packet ${clusterId} --state-file <state-file>\n` +
|
|
115
|
+
` 2. Dispatch the Librarian with the generated packet path as the sole session prompt.\n` +
|
|
116
|
+
` 3. Wait for the Librarian to write its sealed result.\n` +
|
|
117
|
+
` 4. Re-run finalize.\n` +
|
|
118
|
+
`Use --skip-librarian to bypass this gate for backward compatibility.`);
|
|
119
|
+
}
|
|
120
|
+
let packetJson;
|
|
121
|
+
try {
|
|
122
|
+
packetJson = JSON.parse((0, node_fs_1.readFileSync)(latestPacket, "utf-8"));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return `Cannot read Librarian packet at ${latestPacket}. Regenerate with: npm run polaris -- librarian packet ${clusterId}`;
|
|
126
|
+
}
|
|
127
|
+
const resultPath = packetJson["result_path"];
|
|
128
|
+
if (typeof resultPath !== "string") {
|
|
129
|
+
return `Librarian packet is malformed: missing result_path. Regenerate with: npm run polaris -- librarian packet ${clusterId}`;
|
|
130
|
+
}
|
|
131
|
+
if (!(0, node_fs_1.existsSync)(resultPath)) {
|
|
132
|
+
return ("Closeout Librarian has not written its sealed result yet.\n" +
|
|
133
|
+
` Expected result at: ${resultPath}\n` +
|
|
134
|
+
` Dispatch the Librarian session and wait for it to write its sealed result, then re-run finalize.`);
|
|
135
|
+
}
|
|
136
|
+
let resultJson;
|
|
137
|
+
try {
|
|
138
|
+
resultJson = JSON.parse((0, node_fs_1.readFileSync)(resultPath, "utf-8"));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return `Cannot read Librarian result at ${resultPath}. The file may be corrupt.`;
|
|
142
|
+
}
|
|
143
|
+
const validationErrors = (0, closeout_librarian_types_js_1.validateCloseoutLibrarianResult)(resultJson);
|
|
144
|
+
if (validationErrors.length > 0) {
|
|
145
|
+
return `Librarian result is invalid: ${validationErrors.join("; ")}`;
|
|
146
|
+
}
|
|
147
|
+
// Cross-validate dispatch_id and run_id
|
|
148
|
+
const result = resultJson;
|
|
149
|
+
if (packetJson["dispatch_id"] !== result.dispatch_id) {
|
|
150
|
+
return `Librarian result dispatch_id mismatch (packet: ${packetJson["dispatch_id"]}, result: ${result.dispatch_id}). Regenerate and re-dispatch.`;
|
|
151
|
+
}
|
|
152
|
+
if (packetJson["run_id"] !== result.run_id) {
|
|
153
|
+
return `Librarian result run_id mismatch (packet: ${packetJson["run_id"]}, result: ${result.run_id}).`;
|
|
154
|
+
}
|
|
155
|
+
// Validate files_committed against packet scope constraints
|
|
156
|
+
const allowedWritePaths = (packetJson["allowed_write_paths"] ?? []);
|
|
157
|
+
const prohibitedWritePaths = (packetJson["prohibited_write_paths"] ?? []);
|
|
158
|
+
const filesCommitted = result.files_committed ?? [];
|
|
159
|
+
for (const file of filesCommitted) {
|
|
160
|
+
const prohibitedMatch = prohibitedWritePaths.find((pattern) => (0, git_custody_js_1.patternMatchesPath)(pattern, file));
|
|
161
|
+
if (prohibitedMatch) {
|
|
162
|
+
return `Librarian wrote to prohibited path: ${file} (matched pattern: ${prohibitedMatch})`;
|
|
163
|
+
}
|
|
164
|
+
const allowedMatch = allowedWritePaths.find((pattern) => (0, git_custody_js_1.patternMatchesPath)(pattern, file));
|
|
165
|
+
if (allowedMatch)
|
|
166
|
+
continue; // explicitly allowed
|
|
167
|
+
return `Librarian wrote to out-of-scope path: ${file} (not in allowed_write_paths)`;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
return (0, closeout_librarian_types_js_1.checkLibrarianResultGate)(result);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
return `Librarian result gate error: ${err instanceof Error ? err.message : String(err)}`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function runFinalize(options) {
|
|
177
|
+
const { repoRoot, stateFile, dryRun, skipDelivery, skipLibrarian } = options;
|
|
178
|
+
const config = (0, loader_js_1.loadConfig)(repoRoot);
|
|
179
|
+
// Step 1: polaris map update --changed
|
|
180
|
+
console.log("[1/14] Updating map..."); // Step count updated
|
|
181
|
+
(0, _01_map_update_js_1.stepMapUpdate)(repoRoot);
|
|
182
|
+
// Step 2: polaris map validate — fail fast
|
|
183
|
+
console.log("[2/14] Validating map..."); // Step count updated
|
|
184
|
+
(0, _02_map_validate_js_1.stepMapValidate)(repoRoot);
|
|
185
|
+
// Step 3: Validate current-state.json schema
|
|
186
|
+
console.log("[3/14] Validating current-state.json schema..."); // Step count updated
|
|
187
|
+
let rawState;
|
|
188
|
+
try {
|
|
189
|
+
rawState = (0, checkpoint_js_1.readState)(stateFile);
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
193
|
+
process.stderr.write(`finalize aborted: cannot read state file ${stateFile}: ${msg}\n`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
(0, _03_schema_validate_js_1.stepSchemaValidate)(rawState);
|
|
197
|
+
let state = rawState;
|
|
198
|
+
// Preflight: state file authority gate (must run before Step 4)
|
|
199
|
+
const branch = getBranch(repoRoot);
|
|
200
|
+
validateStateFilePath(stateFile);
|
|
201
|
+
validateClusterIdMatchesBranch(state.cluster_id, branch);
|
|
202
|
+
validateStateBranchMatchesGitBranch(state.branch, branch);
|
|
203
|
+
// Step 4: Run configured checks
|
|
204
|
+
const checks = config.finalize?.runChecks ?? [];
|
|
205
|
+
if (checks.length > 0) {
|
|
206
|
+
console.log(`[4/14] Running ${checks.length} configured check(s) and staging preflight...`); // Step count updated
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
console.log("[4/14] Running staging preflight..."); // Step count updated
|
|
210
|
+
}
|
|
211
|
+
(0, _04_run_checks_js_1.stepRunChecks)(repoRoot, checks, { activeClusterId: state.cluster_id, skipDelivery });
|
|
212
|
+
// Step 4.5: Canon reconciliation check
|
|
213
|
+
const canonCheckEnabled = config.canon?.checkOnFinalize !== false;
|
|
214
|
+
if (canonCheckEnabled) {
|
|
215
|
+
console.log("[4.5/14] Running canon reconciliation check..."); // Step count updated
|
|
216
|
+
let changedFiles = [];
|
|
217
|
+
try {
|
|
218
|
+
const baseBranch = config.finalize?.targetBranch ?? "main";
|
|
219
|
+
const diffOutput = (0, node_child_process_1.execFileSync)("git", ["diff", "--name-only", `${baseBranch}...HEAD`], { cwd: repoRoot, encoding: "utf-8" });
|
|
220
|
+
changedFiles = diffOutput.trim().split("\n").filter(Boolean);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
// Fail closed: if git diff fails, we cannot determine changed files for canon check
|
|
224
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
225
|
+
console.error(`Error: git diff failed during canon check: ${msg}`);
|
|
226
|
+
throw new Error(`Canon check cannot proceed: git diff failed: ${msg}`);
|
|
227
|
+
}
|
|
228
|
+
const artifactDirForCheck = state.artifact_dir ?? (0, node_path_1.join)(repoRoot, ".taskchain_artifacts", "polaris-run");
|
|
229
|
+
const telemetryFileForCheck = (0, node_path_1.join)(artifactDirForCheck, "runs", state.run_id, "telemetry.jsonl");
|
|
230
|
+
const canonResult = (0, canon_check_js_1.runCanonCheck)({
|
|
231
|
+
repoRoot,
|
|
232
|
+
changedFiles,
|
|
233
|
+
childId: undefined,
|
|
234
|
+
runId: state.run_id,
|
|
235
|
+
telemetryFile: telemetryFileForCheck,
|
|
236
|
+
});
|
|
237
|
+
if (canonResult.outcome === "stale-implementation") {
|
|
238
|
+
const conflict = canonResult.conflicts.find((c) => c.type === "stale-implementation");
|
|
239
|
+
process.stderr.write([
|
|
240
|
+
`Canon conflict halt — finalize blocked. PR will not be created.`,
|
|
241
|
+
`Canon file: ${conflict?.canonFile ?? "unknown"}`,
|
|
242
|
+
`Statement: ${conflict?.statement ?? ""}`,
|
|
243
|
+
`Affected file: ${conflict?.changedFile ?? ""}`,
|
|
244
|
+
`Detail: ${conflict?.detail ?? ""}`,
|
|
245
|
+
`Resolution: Update the canon file or implement the missing piece before finalizing.`,
|
|
246
|
+
].join("\n") + "\n");
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Step 5: Generate run-report.md (written once, never updated)
|
|
251
|
+
console.log("[5/14] Generating run-report.md..."); // Step count updated
|
|
252
|
+
const reportPath = (0, _05_generate_report_js_1.stepGenerateReport)(repoRoot, state, branch, true);
|
|
253
|
+
if (dryRun) {
|
|
254
|
+
console.log("[6–14/14] Dry run — skipping reconciliation, commit and delivery.");
|
|
255
|
+
console.log("Finalize dry run complete.");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
// Step 5.5: Implementation evidence gate
|
|
259
|
+
// Require at least one non-artifact staged file before committing. A finalize
|
|
260
|
+
// commit with only Polaris artifact files means no real implementation work
|
|
261
|
+
// was recorded — abort to prevent a phantom delivery.
|
|
262
|
+
{
|
|
263
|
+
const stagedOutput = (0, node_child_process_1.execFileSync)("git", ["diff", "--cached", "--name-only"], {
|
|
264
|
+
cwd: repoRoot,
|
|
265
|
+
encoding: "utf-8",
|
|
266
|
+
}).trim();
|
|
267
|
+
const stagedFiles = stagedOutput ? stagedOutput.split("\n").filter(Boolean) : [];
|
|
268
|
+
const implFiles = stagedFiles.filter((f) => (0, artifact_policy_js_1.classifyArtifactPath)(f, state.cluster_id) === "non-artifact");
|
|
269
|
+
if (implFiles.length === 0) {
|
|
270
|
+
const evidenceReport = (0, finalize_evidence_js_1.verifyCompletedChildFinalizeEvidence)(repoRoot, stateFile);
|
|
271
|
+
if (!evidenceReport.ok) {
|
|
272
|
+
process.stderr.write("finalize aborted: No implementation evidence found. " +
|
|
273
|
+
"No non-artifact source files are staged and canonical completed-child evidence failed.\n" +
|
|
274
|
+
`${(0, finalize_evidence_js_1.formatFinalizeEvidenceFailures)(evidenceReport.failures)}\n`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Step 5.6: Branch custody verification
|
|
280
|
+
// When the cluster state records a delivery_branch and base_branch (set by dispatch),
|
|
281
|
+
// verify that base..delivery_branch contains at least one non-artifact source change
|
|
282
|
+
// and that no completed child's commit is already reachable from the base branch.
|
|
283
|
+
//
|
|
284
|
+
// Skipped when no custody record is present (backward compatibility with runs
|
|
285
|
+
// that did not go through the custody-aware dispatch path) or when
|
|
286
|
+
// loop.allowBranchDivergence is true (direct-main mode).
|
|
287
|
+
{
|
|
288
|
+
const clusterState = (0, store_js_1.readClusterStateSync)(state.cluster_id, repoRoot);
|
|
289
|
+
const baseBranch = clusterState?.base_branch;
|
|
290
|
+
const deliveryBranch = clusterState?.delivery_branch;
|
|
291
|
+
const directMainMode = config.loop?.allowBranchDivergence === true;
|
|
292
|
+
if (!directMainMode && baseBranch && deliveryBranch) {
|
|
293
|
+
// Assert finalize is running on the recorded delivery branch.
|
|
294
|
+
if (branch !== deliveryBranch) {
|
|
295
|
+
process.stderr.write(`finalize aborted: branch custody violation — not on delivery branch. ` +
|
|
296
|
+
`Expected "${deliveryBranch}", got "${branch}".\n`);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
const hasImplChanges = (0, git_custody_js_1.hasNonArtifactSourceChanges)(repoRoot, baseBranch, state.cluster_id, deliveryBranch);
|
|
300
|
+
if (!hasImplChanges) {
|
|
301
|
+
process.stderr.write(`finalize aborted: branch custody violation — no non-artifact source changes found in ` +
|
|
302
|
+
`${baseBranch}...${deliveryBranch}. Child commits may already be on the base branch, ` +
|
|
303
|
+
`or no implementation work was recorded on this delivery branch.\n`);
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
// Check each completed child's commit to verify it is not already on the base branch.
|
|
307
|
+
for (const childId of state.completed_children) {
|
|
308
|
+
const commitHash = clusterState.commits?.[childId] ??
|
|
309
|
+
state.completed_children_results?.[childId]?.commit ??
|
|
310
|
+
null;
|
|
311
|
+
if (!commitHash)
|
|
312
|
+
continue;
|
|
313
|
+
const custodyError = (0, git_custody_js_1.verifyChildCommitCustody)(repoRoot, commitHash, deliveryBranch, baseBranch);
|
|
314
|
+
if (custodyError) {
|
|
315
|
+
process.stderr.write(`finalize aborted: branch custody violation for ${childId}: ${custodyError}\n`);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Step 5.7: Unconditional delivery integrity gate
|
|
322
|
+
// Verifies the delivery branch contains actual implementation work relative to the base branch.
|
|
323
|
+
// Runs regardless of whether branch custody records were established in cluster state,
|
|
324
|
+
// closing the gap that allowed PR #93 to claim delivery when implementation was already on main.
|
|
325
|
+
{
|
|
326
|
+
const directMainMode = config.loop?.allowBranchDivergence === true;
|
|
327
|
+
if (!directMainMode) {
|
|
328
|
+
const clusterStateForIntegrity = (0, store_js_1.readClusterStateSync)(state.cluster_id, repoRoot);
|
|
329
|
+
const integrityBaseBranch = clusterStateForIntegrity?.base_branch ??
|
|
330
|
+
config.finalize?.targetBranch ??
|
|
331
|
+
"main";
|
|
332
|
+
const childCommits = {};
|
|
333
|
+
for (const childId of state.completed_children) {
|
|
334
|
+
const commit = clusterStateForIntegrity?.commits?.[childId] ??
|
|
335
|
+
state.completed_children_results?.[childId]?.commit ??
|
|
336
|
+
null;
|
|
337
|
+
if (commit)
|
|
338
|
+
childCommits[childId] = commit;
|
|
339
|
+
}
|
|
340
|
+
const integrityResult = (0, delivery_integrity_js_1.validateDeliveryIntegrity)({
|
|
341
|
+
repoRoot,
|
|
342
|
+
currentBranch: branch,
|
|
343
|
+
baseBranch: integrityBaseBranch,
|
|
344
|
+
clusterId: state.cluster_id,
|
|
345
|
+
completedChildren: state.completed_children,
|
|
346
|
+
childCommits,
|
|
347
|
+
});
|
|
348
|
+
if (!integrityResult.ok) {
|
|
349
|
+
process.stderr.write(`finalize aborted: delivery integrity check failed (${integrityResult.kind}) — ${integrityResult.reason}\n`);
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Step 6: Tracker Reconciliation
|
|
355
|
+
// LinearAdapter is sync-in only; only McpBridgeAdapter supports full reconciliation.
|
|
356
|
+
const trackerType = config.tracker?.adapter;
|
|
357
|
+
if (!trackerType) {
|
|
358
|
+
console.log("[6/14] Tracker not configured — skipping reconciliation.");
|
|
359
|
+
}
|
|
360
|
+
else if (trackerType === "linear") {
|
|
361
|
+
console.log("[6/14] Linear adapter is sync-in only — skipping reconciliation (use mcp-bridge for two-way sync).");
|
|
362
|
+
}
|
|
363
|
+
else if (trackerType === "mcp-bridge") {
|
|
364
|
+
console.log("[6/14] Running tracker reconciliation...");
|
|
365
|
+
try {
|
|
366
|
+
const localGraph = await local_graph_js_1.LocalGraph.load(state.cluster_id, repoRoot);
|
|
367
|
+
const { McpBridgeAdapter } = await import("../tracker/adapters/mcp-bridge.js");
|
|
368
|
+
const trackerAdapter = new McpBridgeAdapter();
|
|
369
|
+
const trackerSyncService = new index_js_1.TrackerSyncService(trackerAdapter, localGraph, {
|
|
370
|
+
repoRoot,
|
|
371
|
+
clusterId: state.cluster_id,
|
|
372
|
+
});
|
|
373
|
+
await trackerSyncService.ready;
|
|
374
|
+
const reconciliationReport = await trackerSyncService.reconcile(dryRun);
|
|
375
|
+
console.log("Tracker Reconciliation Report:", reconciliationReport);
|
|
376
|
+
if (reconciliationReport.conflictsDetectedCount > 0 || reconciliationReport.failedMutationsCount > 0) {
|
|
377
|
+
const summary = reconciliationReport.details.join(" | ");
|
|
378
|
+
throw new Error(`tracker reconciliation requires attention (conflicts=${reconciliationReport.conflictsDetectedCount}, failed=${reconciliationReport.failedMutationsCount})${summary ? `: ${summary}` : ""}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
console.error("Error during tracker reconciliation:", error);
|
|
383
|
+
process.stderr.write(`finalize aborted: tracker reconciliation failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
console.warn(`[6/14] Unknown tracker adapter '${trackerType}' — skipping reconciliation.`);
|
|
389
|
+
}
|
|
390
|
+
// Step 7: Single final commit: source changes + durable Polaris artifacts
|
|
391
|
+
console.log("[7/14] Committing durable Polaris state + map..."); // Step count updated
|
|
392
|
+
const resolvedStateFile = (0, node_path_1.resolve)(stateFile);
|
|
393
|
+
(0, _06_commit_js_1.stepCommit)(repoRoot, state, resolvedStateFile, reportPath);
|
|
394
|
+
if (skipDelivery) {
|
|
395
|
+
console.log("[8–14/14] Delivery skipped (--skip-delivery).");
|
|
396
|
+
console.log("polaris finalize steps 1–7 complete.");
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// Step 8: Closeout Librarian gate
|
|
400
|
+
if (!skipLibrarian) {
|
|
401
|
+
console.log("[8/14] Checking Closeout Librarian gate...");
|
|
402
|
+
const librarianBlocker = checkLibrarianGate(repoRoot, state.cluster_id);
|
|
403
|
+
if (librarianBlocker) {
|
|
404
|
+
process.stderr.write(`finalize aborted: Closeout Librarian gate failed.\n${librarianBlocker}\n`);
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
console.log("[8/14] Closeout Librarian gate passed.");
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
console.log("[8/14] Closeout Librarian gate skipped (--skip-librarian).");
|
|
411
|
+
}
|
|
412
|
+
// Step 9: git push
|
|
413
|
+
console.log("[9/14] Pushing branch...");
|
|
414
|
+
(0, _07_push_js_1.stepPush)(repoRoot, branch);
|
|
415
|
+
// Step 10: Create draft PR
|
|
416
|
+
const prDraft = config.finalize?.prDraft ?? true;
|
|
417
|
+
console.log("[10/14] Creating draft PR...");
|
|
418
|
+
const prUrl = (0, _08_create_pr_js_1.stepCreatePr)(repoRoot, branch, state, prDraft);
|
|
419
|
+
// Step 11: Write PR URL to current-state.json
|
|
420
|
+
console.log("[11/14] Writing PR URL to state...");
|
|
421
|
+
state = (0, _09_update_state_js_1.stepUpdateState)(resolvedStateFile, state, prUrl);
|
|
422
|
+
// Step 12: Append JSONL events
|
|
423
|
+
console.log("[12/14] Appending JSONL events...");
|
|
424
|
+
const artifactDir = state.artifact_dir ?? (0, node_path_1.join)(repoRoot, ".taskchain_artifacts", "polaris-run");
|
|
425
|
+
const telemetryFile = (0, node_path_1.join)(artifactDir, "runs", state.run_id, "telemetry.jsonl");
|
|
426
|
+
(0, _10_append_jsonl_js_1.stepAppendJsonl)(telemetryFile, state, prUrl);
|
|
427
|
+
// Step 13: Update Linear parent issue
|
|
428
|
+
console.log("[13/14] Updating Linear...");
|
|
429
|
+
const linearEnabled = config.tracker?.linear?.enabled ?? false;
|
|
430
|
+
const lifecyclePolicy = config.tracker?.lifecyclePolicy;
|
|
431
|
+
await (0, _11_update_linear_js_1.stepUpdateLinear)(state, branch, prUrl, true, linearEnabled, state.cluster_id, lifecyclePolicy);
|
|
432
|
+
// Step 14: Archive run snapshot
|
|
433
|
+
console.log("[14/14] Archiving run snapshot...");
|
|
434
|
+
(0, _12_archive_js_1.stepArchive)(repoRoot, state, resolvedStateFile, reportPath);
|
|
435
|
+
console.log("polaris finalize complete.");
|
|
436
|
+
}
|
|
437
|
+
function failMissingSubcommand(command, commandName) {
|
|
438
|
+
const unknownSubcommand = command.args[0];
|
|
439
|
+
const message = unknownSubcommand
|
|
440
|
+
? `error: unknown command '${unknownSubcommand}' for '${commandName}'. Run '${commandName} --help'.`
|
|
441
|
+
: `error: missing command for '${commandName}'. Run '${commandName} --help'.`;
|
|
442
|
+
command.error(message, {
|
|
443
|
+
code: "commander.missingCommand",
|
|
444
|
+
exitCode: 1,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
function createFinalizeCommand(handlers = {}) {
|
|
448
|
+
const finalizeHandler = handlers.runFinalize ?? runFinalize;
|
|
449
|
+
const repoRootDefault = handlers.repoRoot ?? process.cwd();
|
|
450
|
+
const finalize = new commander_1.Command("finalize")
|
|
451
|
+
.description("manual/operator-triggered delivery; finalize run performs delivery unless --dry-run or --skip-delivery is supplied")
|
|
452
|
+
.showHelpAfterError()
|
|
453
|
+
.showSuggestionAfterError();
|
|
454
|
+
finalize.action(() => failMissingSubcommand(finalize, "polaris finalize"));
|
|
455
|
+
finalize
|
|
456
|
+
.command("run")
|
|
457
|
+
.description("mutating: run manual/operator-triggered finalize and perform delivery")
|
|
458
|
+
.option("-r, --repo-root <path>", "Repository root", repoRootDefault)
|
|
459
|
+
.option("--state-file <path>", "Path to current-state.json")
|
|
460
|
+
.option("--dry-run", "non-mutating preview: validate and generate report without committing or pushing")
|
|
461
|
+
.option("--skip-delivery", "perform local finalize steps only; skip push/PR/Linear/archive")
|
|
462
|
+
.option("--skip-librarian", "skip the Closeout Librarian gate (backward compatibility only)")
|
|
463
|
+
.action((options) => {
|
|
464
|
+
const repoRoot = options.repoRoot;
|
|
465
|
+
const stateFile = options.stateFile ??
|
|
466
|
+
(0, node_path_1.join)(repoRoot, ".taskchain_artifacts", "polaris-run", "current-state.json");
|
|
467
|
+
finalizeHandler({ repoRoot, stateFile, dryRun: options.dryRun, skipDelivery: options.skipDelivery, skipLibrarian: options.skipLibrarian })
|
|
468
|
+
.catch((err) => {
|
|
469
|
+
process.stderr.write(`finalize error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
470
|
+
process.exit(1);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
return finalize;
|
|
474
|
+
}
|