@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,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const vitest_1 = require("vitest");
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const node_path_1 = require("node:path");
|
|
39
|
+
const init_js_1 = require("./init.js");
|
|
40
|
+
vitest_1.vi.mock("node:fs", async (importOriginal) => {
|
|
41
|
+
const actual = await importOriginal();
|
|
42
|
+
return {
|
|
43
|
+
...actual,
|
|
44
|
+
existsSync: vitest_1.vi.fn(),
|
|
45
|
+
readFileSync: vitest_1.vi.fn(),
|
|
46
|
+
writeFileSync: vitest_1.vi.fn(),
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
const mockedExistsSync = vitest_1.vi.mocked(fs.existsSync);
|
|
50
|
+
const mockedReadFileSync = vitest_1.vi.mocked(fs.readFileSync);
|
|
51
|
+
const mockedWriteFileSync = vitest_1.vi.mocked(fs.writeFileSync);
|
|
52
|
+
let stdoutOutput = "";
|
|
53
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
54
|
+
(0, vitest_1.beforeEach)(() => {
|
|
55
|
+
vitest_1.vi.resetAllMocks();
|
|
56
|
+
stdoutOutput = "";
|
|
57
|
+
vitest_1.vi.spyOn(process.stdout, "write").mockImplementation((data) => {
|
|
58
|
+
stdoutOutput += String(data);
|
|
59
|
+
return true;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.afterEach)(() => {
|
|
63
|
+
vitest_1.vi.restoreAllMocks();
|
|
64
|
+
});
|
|
65
|
+
const REPO_ROOT = "/fake-repo";
|
|
66
|
+
const CONFIG_PATH = (0, node_path_1.join)(REPO_ROOT, "polaris.config.json");
|
|
67
|
+
(0, vitest_1.describe)("runInit — no existing config", () => {
|
|
68
|
+
(0, vitest_1.it)("writes a new config with compactionProviders when providers are detected", () => {
|
|
69
|
+
mockedExistsSync.mockReturnValue(false);
|
|
70
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman"]);
|
|
71
|
+
(0, init_js_1.runInit)({
|
|
72
|
+
repoRoot: REPO_ROOT,
|
|
73
|
+
detectProviders: detect,
|
|
74
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
75
|
+
});
|
|
76
|
+
(0, vitest_1.expect)(mockedWriteFileSync).toHaveBeenCalledOnce();
|
|
77
|
+
const [path, content] = mockedWriteFileSync.mock.calls[0];
|
|
78
|
+
(0, vitest_1.expect)(path).toBe(CONFIG_PATH);
|
|
79
|
+
const written = JSON.parse(content);
|
|
80
|
+
(0, vitest_1.expect)(written).toMatchObject({
|
|
81
|
+
version: "1.0",
|
|
82
|
+
providers: { compactionProviders: ["caveman"] },
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
(0, vitest_1.it)("writes config WITHOUT compactionProviders when no providers detected", () => {
|
|
86
|
+
mockedExistsSync.mockReturnValue(false);
|
|
87
|
+
const detect = vitest_1.vi.fn().mockReturnValue([]);
|
|
88
|
+
(0, init_js_1.runInit)({
|
|
89
|
+
repoRoot: REPO_ROOT,
|
|
90
|
+
detectProviders: detect,
|
|
91
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
92
|
+
});
|
|
93
|
+
(0, vitest_1.expect)(mockedWriteFileSync).toHaveBeenCalledOnce();
|
|
94
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
95
|
+
const written = JSON.parse(content);
|
|
96
|
+
(0, vitest_1.expect)(written).not.toHaveProperty("providers.compactionProviders");
|
|
97
|
+
});
|
|
98
|
+
(0, vitest_1.it)("includes both caveman and gitnexus when both detected", () => {
|
|
99
|
+
mockedExistsSync.mockReturnValue(false);
|
|
100
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman", "gitnexus"]);
|
|
101
|
+
(0, init_js_1.runInit)({
|
|
102
|
+
repoRoot: REPO_ROOT,
|
|
103
|
+
detectProviders: detect,
|
|
104
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
105
|
+
});
|
|
106
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
107
|
+
const written = JSON.parse(content);
|
|
108
|
+
(0, vitest_1.expect)(written.providers.compactionProviders).toEqual([
|
|
109
|
+
"caveman",
|
|
110
|
+
"gitnexus",
|
|
111
|
+
]);
|
|
112
|
+
});
|
|
113
|
+
(0, vitest_1.it)("writes repoAnalysis.preferred when a repo-analysis provider is detected", () => {
|
|
114
|
+
mockedExistsSync.mockReturnValue(false);
|
|
115
|
+
const detectCompaction = vitest_1.vi.fn().mockReturnValue([]);
|
|
116
|
+
const detectRepoAnalysis = vitest_1.vi.fn().mockReturnValue(["gitnexus"]);
|
|
117
|
+
(0, init_js_1.runInit)({
|
|
118
|
+
repoRoot: REPO_ROOT,
|
|
119
|
+
detectProviders: detectCompaction,
|
|
120
|
+
detectRepoAnalysisProviders: detectRepoAnalysis,
|
|
121
|
+
});
|
|
122
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
123
|
+
const written = JSON.parse(content);
|
|
124
|
+
(0, vitest_1.expect)(written).toMatchObject({
|
|
125
|
+
providers: { repoAnalysis: { preferred: "gitnexus" } },
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
(0, vitest_1.describe)("runInit — existing config", () => {
|
|
130
|
+
(0, vitest_1.it)("preserves existing fields when merging", () => {
|
|
131
|
+
const existingConfig = {
|
|
132
|
+
version: "1.0",
|
|
133
|
+
repo: { name: "my-repo" },
|
|
134
|
+
};
|
|
135
|
+
mockedExistsSync.mockReturnValue(true);
|
|
136
|
+
mockedReadFileSync.mockReturnValue(JSON.stringify(existingConfig));
|
|
137
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["gitnexus"]);
|
|
138
|
+
(0, init_js_1.runInit)({
|
|
139
|
+
repoRoot: REPO_ROOT,
|
|
140
|
+
detectProviders: detect,
|
|
141
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
142
|
+
});
|
|
143
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
144
|
+
const written = JSON.parse(content);
|
|
145
|
+
(0, vitest_1.expect)(written).toMatchObject({
|
|
146
|
+
version: "1.0",
|
|
147
|
+
repo: { name: "my-repo" },
|
|
148
|
+
providers: { compactionProviders: ["gitnexus"] },
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
(0, vitest_1.it)("preserves existing providers.repoAnalysis while adding compactionProviders", () => {
|
|
152
|
+
const existingConfig = {
|
|
153
|
+
version: "1.0",
|
|
154
|
+
providers: { repoAnalysis: { preferred: "polaris-map" } },
|
|
155
|
+
};
|
|
156
|
+
mockedExistsSync.mockReturnValue(true);
|
|
157
|
+
mockedReadFileSync.mockReturnValue(JSON.stringify(existingConfig));
|
|
158
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman"]);
|
|
159
|
+
(0, init_js_1.runInit)({
|
|
160
|
+
repoRoot: REPO_ROOT,
|
|
161
|
+
detectProviders: detect,
|
|
162
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue(["gitnexus"]),
|
|
163
|
+
});
|
|
164
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
165
|
+
const written = JSON.parse(content);
|
|
166
|
+
const providers = written.providers;
|
|
167
|
+
(0, vitest_1.expect)(providers.repoAnalysis).toEqual({ preferred: "gitnexus" });
|
|
168
|
+
(0, vitest_1.expect)(providers.compactionProviders).toEqual(["caveman"]);
|
|
169
|
+
});
|
|
170
|
+
(0, vitest_1.it)("preserves repoAnalysis fallback while omitting preferred when no repo-analysis provider is detected", () => {
|
|
171
|
+
const existingConfig = {
|
|
172
|
+
version: "1.0",
|
|
173
|
+
providers: {
|
|
174
|
+
repoAnalysis: { preferred: "gitnexus", fallback: ["polaris-map", "ripgrep"] },
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
mockedExistsSync.mockReturnValue(true);
|
|
178
|
+
mockedReadFileSync.mockReturnValue(JSON.stringify(existingConfig));
|
|
179
|
+
(0, init_js_1.runInit)({
|
|
180
|
+
repoRoot: REPO_ROOT,
|
|
181
|
+
detectProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
182
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
183
|
+
});
|
|
184
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
185
|
+
const written = JSON.parse(content);
|
|
186
|
+
const providers = written.providers;
|
|
187
|
+
(0, vitest_1.expect)(providers.repoAnalysis).toEqual({ fallback: ["polaris-map", "ripgrep"] });
|
|
188
|
+
});
|
|
189
|
+
(0, vitest_1.it)("removes compactionProviders from existing config when none detected", () => {
|
|
190
|
+
const existingConfig = {
|
|
191
|
+
version: "1.0",
|
|
192
|
+
providers: { compactionProviders: ["caveman"] },
|
|
193
|
+
};
|
|
194
|
+
mockedExistsSync.mockReturnValue(true);
|
|
195
|
+
mockedReadFileSync.mockReturnValue(JSON.stringify(existingConfig));
|
|
196
|
+
const detect = vitest_1.vi.fn().mockReturnValue([]);
|
|
197
|
+
(0, init_js_1.runInit)({
|
|
198
|
+
repoRoot: REPO_ROOT,
|
|
199
|
+
detectProviders: detect,
|
|
200
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
201
|
+
});
|
|
202
|
+
const [, content] = mockedWriteFileSync.mock.calls[0];
|
|
203
|
+
const written = JSON.parse(content);
|
|
204
|
+
// providers key may be absent or present but without compactionProviders
|
|
205
|
+
if ("providers" in written && written.providers !== undefined) {
|
|
206
|
+
(0, vitest_1.expect)(written.providers).not.toHaveProperty("compactionProviders");
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
(0, vitest_1.describe)("runInit — dry-run", () => {
|
|
211
|
+
(0, vitest_1.it)("does not write the file in dry-run mode", () => {
|
|
212
|
+
mockedExistsSync.mockReturnValue(false);
|
|
213
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman"]);
|
|
214
|
+
(0, init_js_1.runInit)({
|
|
215
|
+
repoRoot: REPO_ROOT,
|
|
216
|
+
dryRun: true,
|
|
217
|
+
detectProviders: detect,
|
|
218
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
219
|
+
});
|
|
220
|
+
(0, vitest_1.expect)(mockedWriteFileSync).not.toHaveBeenCalled();
|
|
221
|
+
});
|
|
222
|
+
(0, vitest_1.it)("prints the JSON to stdout in dry-run mode", () => {
|
|
223
|
+
mockedExistsSync.mockReturnValue(false);
|
|
224
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman"]);
|
|
225
|
+
(0, init_js_1.runInit)({
|
|
226
|
+
repoRoot: REPO_ROOT,
|
|
227
|
+
dryRun: true,
|
|
228
|
+
detectProviders: detect,
|
|
229
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
230
|
+
});
|
|
231
|
+
const parsed = JSON.parse(stdoutOutput);
|
|
232
|
+
(0, vitest_1.expect)(parsed).toMatchObject({
|
|
233
|
+
providers: { compactionProviders: ["caveman"] },
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
(0, vitest_1.describe)("runInit — stdout messaging", () => {
|
|
238
|
+
(0, vitest_1.it)("prints detected providers in success message", () => {
|
|
239
|
+
mockedExistsSync.mockReturnValue(false);
|
|
240
|
+
const detect = vitest_1.vi.fn().mockReturnValue(["caveman", "gitnexus"]);
|
|
241
|
+
(0, init_js_1.runInit)({
|
|
242
|
+
repoRoot: REPO_ROOT,
|
|
243
|
+
detectProviders: detect,
|
|
244
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
245
|
+
});
|
|
246
|
+
(0, vitest_1.expect)(stdoutOutput).toContain("caveman");
|
|
247
|
+
(0, vitest_1.expect)(stdoutOutput).toContain("gitnexus");
|
|
248
|
+
});
|
|
249
|
+
(0, vitest_1.it)("reports no providers when none detected", () => {
|
|
250
|
+
mockedExistsSync.mockReturnValue(false);
|
|
251
|
+
const detect = vitest_1.vi.fn().mockReturnValue([]);
|
|
252
|
+
(0, init_js_1.runInit)({
|
|
253
|
+
repoRoot: REPO_ROOT,
|
|
254
|
+
detectProviders: detect,
|
|
255
|
+
detectRepoAnalysisProviders: vitest_1.vi.fn().mockReturnValue([]),
|
|
256
|
+
});
|
|
257
|
+
(0, vitest_1.expect)(stdoutOutput).toContain("No compaction providers detected");
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLibrarianCommand = createLibrarianCommand;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const librarian_packet_js_1 = require("../cognition/librarian-packet.js");
|
|
7
|
+
function createLibrarianCommand(options = {}) {
|
|
8
|
+
const repoRootDefault = options.repoRoot ?? (0, node_path_1.resolve)(process.cwd());
|
|
9
|
+
const librarian = new commander_1.Command("librarian")
|
|
10
|
+
.description("Closeout Librarian tools")
|
|
11
|
+
.showHelpAfterError()
|
|
12
|
+
.showSuggestionAfterError();
|
|
13
|
+
librarian
|
|
14
|
+
.command("packet <cluster-id>")
|
|
15
|
+
.description("generate Closeout Librarian packet for a completed cluster")
|
|
16
|
+
.option("-r, --repo-root <path>", "Repository root", repoRootDefault)
|
|
17
|
+
.option("--state-file <path>", "Path to current-state.json (canonical path preferred)")
|
|
18
|
+
.action((clusterId, cmdOptions) => {
|
|
19
|
+
try {
|
|
20
|
+
(0, librarian_packet_js_1.generateLibrarianPacket)({
|
|
21
|
+
repoRoot: cmdOptions.repoRoot,
|
|
22
|
+
clusterId,
|
|
23
|
+
stateFile: cmdOptions.stateFile,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
process.stderr.write(`librarian packet error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return librarian;
|
|
32
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMedicCommand = createMedicCommand;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const chart_id_js_1 = require("../medic/chart-id.js");
|
|
8
|
+
function createMedicCommand(options = {}) {
|
|
9
|
+
const repoRootDefault = options.repoRoot ?? (0, node_path_1.resolve)(process.cwd());
|
|
10
|
+
const medic = new commander_1.Command("medic")
|
|
11
|
+
.description("Medic role tools")
|
|
12
|
+
.showHelpAfterError()
|
|
13
|
+
.showSuggestionAfterError();
|
|
14
|
+
medic
|
|
15
|
+
.command("chart")
|
|
16
|
+
.description("Chart management commands")
|
|
17
|
+
.addCommand(new commander_1.Command("create")
|
|
18
|
+
.description("Scaffold a new chart with a valid Chart ID")
|
|
19
|
+
.option("-r, --repo-root <path>", "Repository root", repoRootDefault)
|
|
20
|
+
.option("--cluster-id <id>", "Cluster ID for this chart", "UNKNOWN")
|
|
21
|
+
.option("--route <path>", "Route path for this chart", "UNKNOWN")
|
|
22
|
+
.option("--status <status>", "Chart status", "draft")
|
|
23
|
+
.action((cmdOptions) => {
|
|
24
|
+
try {
|
|
25
|
+
createChart({
|
|
26
|
+
repoRoot: cmdOptions.repoRoot,
|
|
27
|
+
clusterId: cmdOptions.clusterId,
|
|
28
|
+
route: cmdOptions.route,
|
|
29
|
+
status: cmdOptions.status,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
process.stderr.write(`medic chart create error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}));
|
|
37
|
+
return medic;
|
|
38
|
+
}
|
|
39
|
+
function createChart(options) {
|
|
40
|
+
const { repoRoot, clusterId, route, status } = options;
|
|
41
|
+
// Ensure charts directory exists
|
|
42
|
+
const chartsDir = (0, node_path_1.resolve)(repoRoot, "smartdocs/medic/charts");
|
|
43
|
+
(0, node_fs_1.mkdirSync)(chartsDir, { recursive: true });
|
|
44
|
+
// Generate next Chart ID
|
|
45
|
+
const chartId = (0, chart_id_js_1.generateNextChartId)(chartsDir);
|
|
46
|
+
// Get current timestamp
|
|
47
|
+
const now = new Date().toISOString();
|
|
48
|
+
// Create chart content
|
|
49
|
+
const chartContent = `---
|
|
50
|
+
chart_id: ${chartId.full}
|
|
51
|
+
cluster_id: ${clusterId}
|
|
52
|
+
route: ${route}
|
|
53
|
+
status: ${status}
|
|
54
|
+
related_charts: []
|
|
55
|
+
created: ${now}
|
|
56
|
+
updated: ${now}
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Problem
|
|
60
|
+
|
|
61
|
+
Describe the problem diagnosed by the Medic.
|
|
62
|
+
|
|
63
|
+
## Symptoms
|
|
64
|
+
|
|
65
|
+
List the symptoms that led to this diagnosis.
|
|
66
|
+
|
|
67
|
+
## Root Cause
|
|
68
|
+
|
|
69
|
+
Explain the root cause of the failure.
|
|
70
|
+
|
|
71
|
+
## Affected Files
|
|
72
|
+
|
|
73
|
+
List the files affected by this issue.
|
|
74
|
+
|
|
75
|
+
## Treatment
|
|
76
|
+
|
|
77
|
+
Describe the treatment applied to fix the issue.
|
|
78
|
+
|
|
79
|
+
## Validation
|
|
80
|
+
|
|
81
|
+
Describe how the fix was validated.
|
|
82
|
+
|
|
83
|
+
## Prevention
|
|
84
|
+
|
|
85
|
+
Describe how to prevent this issue from recurring.
|
|
86
|
+
|
|
87
|
+
## When To Read This Chart
|
|
88
|
+
|
|
89
|
+
Describe the conditions under which this chart should be retrieved.
|
|
90
|
+
`;
|
|
91
|
+
// Write chart file
|
|
92
|
+
const chartPath = (0, node_path_1.resolve)(chartsDir, `${chartId.full}.md`);
|
|
93
|
+
(0, node_fs_1.writeFileSync)(chartPath, chartContent, "utf-8");
|
|
94
|
+
process.stdout.write(`Created chart: ${chartPath}\n`);
|
|
95
|
+
process.stdout.write(`Chart ID: ${chartId.full}\n`);
|
|
96
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
(0, vitest_1.describe)("CLI startup", () => {
|
|
5
|
+
(0, vitest_1.it)("config show does not import @tool-server/linear", async () => {
|
|
6
|
+
vitest_1.vi.resetModules();
|
|
7
|
+
const importedToolServer = vitest_1.vi.fn();
|
|
8
|
+
vitest_1.vi.doMock("@tool-server/linear", () => {
|
|
9
|
+
importedToolServer();
|
|
10
|
+
throw new Error("unexpected @tool-server/linear import");
|
|
11
|
+
});
|
|
12
|
+
const { createPolarisCommand } = await import("./index.js");
|
|
13
|
+
const runConfigShow = vitest_1.vi.fn();
|
|
14
|
+
const program = createPolarisCommand({
|
|
15
|
+
repoRoot: "/repo",
|
|
16
|
+
runConfigShow,
|
|
17
|
+
});
|
|
18
|
+
await (0, vitest_1.expect)(program.parseAsync(["node", "polaris", "config", "show"], { from: "node" })).resolves.toBeDefined();
|
|
19
|
+
(0, vitest_1.expect)(runConfigShow).toHaveBeenCalledWith({ repoRoot: "/repo" });
|
|
20
|
+
(0, vitest_1.expect)(importedToolServer).not.toHaveBeenCalled();
|
|
21
|
+
vitest_1.vi.doUnmock("@tool-server/linear");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTrackerCommand = createTrackerCommand;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const local_graph_js_1 = require("../tracker/local-graph.js");
|
|
7
|
+
const index_js_1 = require("../tracker/sync/index.js");
|
|
8
|
+
const index_js_2 = require("../tracker/adapters/linear/index.js");
|
|
9
|
+
const loader_js_1 = require("../config/loader.js");
|
|
10
|
+
function createTrackerCommand(options) {
|
|
11
|
+
const trackerCommand = new commander_1.Command('tracker')
|
|
12
|
+
.description('Manage tracker synchronization and reconciliation');
|
|
13
|
+
trackerCommand
|
|
14
|
+
.command('sync-in [trackerId]')
|
|
15
|
+
.description('Synchronize data from a tracker into the local graph.')
|
|
16
|
+
.option('--adapter <adapterName>', 'Specify the tracker adapter to use (e.g., linear, mcp-bridge)')
|
|
17
|
+
.option('-r, --repo-root <path>', 'Repository root', options.repoRoot)
|
|
18
|
+
.action(async (trackerId, commandOptions) => {
|
|
19
|
+
const repoRoot = (0, node_path_1.resolve)(commandOptions.repoRoot ?? options.repoRoot);
|
|
20
|
+
const config = (0, loader_js_1.loadConfig)(repoRoot);
|
|
21
|
+
const adapterName = commandOptions.adapter ?? config.tracker?.adapter ?? 'linear';
|
|
22
|
+
if (!trackerId) {
|
|
23
|
+
console.error("Error: trackerId is required (e.g., 'polaris tracker sync-in POL-198').");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
console.log(`Executing 'tracker sync-in' for tracker: ${trackerId} using adapter: ${adapterName}`);
|
|
27
|
+
if (adapterName === 'linear') {
|
|
28
|
+
// LinearAdapter is a pull-only sync-in adapter — use it directly
|
|
29
|
+
const adapter = new index_js_2.LinearAdapter(config);
|
|
30
|
+
let graph;
|
|
31
|
+
try {
|
|
32
|
+
graph = await adapter.syncIn(trackerId);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error(`sync-in failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
let writtenPath;
|
|
39
|
+
try {
|
|
40
|
+
writtenPath = await graph.save(trackerId, repoRoot);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
console.error(`sync-in: failed to persist graph: ${err instanceof Error ? err.message : String(err)}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
console.log(`sync-in complete. Active cluster: ${graph.fullGraph.activeCluster}`);
|
|
47
|
+
console.log(`Written: ${writtenPath}`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (adapterName === 'mcp-bridge') {
|
|
51
|
+
let localGraph;
|
|
52
|
+
try {
|
|
53
|
+
localGraph = await local_graph_js_1.LocalGraph.load(trackerId, repoRoot);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.error(`Failed to load local graph for cluster '${trackerId}': ${err instanceof Error ? err.message : String(err)}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const { McpBridgeAdapter } = await import('../tracker/adapters/mcp-bridge.js');
|
|
60
|
+
const adapter = new McpBridgeAdapter();
|
|
61
|
+
const service = new index_js_1.TrackerSyncService(adapter, localGraph, {
|
|
62
|
+
repoRoot,
|
|
63
|
+
clusterId: trackerId,
|
|
64
|
+
});
|
|
65
|
+
await service.ready;
|
|
66
|
+
const report = await service.syncIn({ trackerId });
|
|
67
|
+
console.log('Sync-in Report:', report);
|
|
68
|
+
// Persist graph state changes
|
|
69
|
+
let writtenPath;
|
|
70
|
+
try {
|
|
71
|
+
writtenPath = await localGraph.save(trackerId, repoRoot);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.error(`sync-in: failed to persist graph: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
console.log(`Graph persisted: ${writtenPath}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.error(`Unknown adapter: ${adapterName}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|
|
83
|
+
trackerCommand
|
|
84
|
+
.command('reconcile <trackerId>')
|
|
85
|
+
.description('Reconcile local mutations with the remote tracker.')
|
|
86
|
+
.option('--dry-run', 'Perform a dry run without applying changes to the remote tracker.')
|
|
87
|
+
.option('--adapter <adapterName>', 'Specify the tracker adapter to use (e.g., mcp-bridge)')
|
|
88
|
+
.option('-r, --repo-root <path>', 'Repository root', options.repoRoot)
|
|
89
|
+
.action(async (trackerId, commandOptions) => {
|
|
90
|
+
const repoRoot = (0, node_path_1.resolve)(commandOptions.repoRoot ?? options.repoRoot);
|
|
91
|
+
const config = (0, loader_js_1.loadConfig)(repoRoot);
|
|
92
|
+
const adapterName = commandOptions.adapter ?? config.tracker?.adapter ?? 'mcp-bridge';
|
|
93
|
+
if (adapterName === 'linear') {
|
|
94
|
+
console.error("The 'linear' adapter is sync-in only and does not support reconciliation. Use 'mcp-bridge' for reconciliation.");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
else if (adapterName !== 'mcp-bridge') {
|
|
98
|
+
console.error(`Unknown adapter: ${adapterName}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
console.log(`Executing 'tracker reconcile' for cluster '${trackerId}' (dryRun: ${commandOptions.dryRun}) using adapter: ${adapterName}`);
|
|
102
|
+
let localGraph;
|
|
103
|
+
try {
|
|
104
|
+
localGraph = await local_graph_js_1.LocalGraph.load(trackerId, repoRoot);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error(`Failed to load local graph for cluster '${trackerId}': ${err instanceof Error ? err.message : String(err)}`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const { McpBridgeAdapter } = await import('../tracker/adapters/mcp-bridge.js');
|
|
111
|
+
const adapter = new McpBridgeAdapter();
|
|
112
|
+
const service = new index_js_1.TrackerSyncService(adapter, localGraph, {
|
|
113
|
+
repoRoot,
|
|
114
|
+
clusterId: trackerId,
|
|
115
|
+
});
|
|
116
|
+
await service.ready;
|
|
117
|
+
const report = await service.reconcile(commandOptions.dryRun);
|
|
118
|
+
console.log('Reconciliation Report:', report);
|
|
119
|
+
// Persist graph state changes after reconciliation
|
|
120
|
+
try {
|
|
121
|
+
const writtenPath = await localGraph.save(trackerId, repoRoot);
|
|
122
|
+
console.log(`Graph persisted: ${writtenPath}`);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
console.error(`reconcile: failed to persist graph: ${err instanceof Error ? err.message : String(err)}`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return trackerCommand;
|
|
130
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const vitest_1 = require("vitest");
|
|
40
|
+
const promises_1 = require("node:fs/promises");
|
|
41
|
+
const node_os_1 = require("node:os");
|
|
42
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
43
|
+
const tracker_js_1 = require("./tracker.js");
|
|
44
|
+
const local_graph_js_1 = require("../tracker/local-graph.js");
|
|
45
|
+
const linearModule = __importStar(require("../tracker/adapters/linear/index.js"));
|
|
46
|
+
const configLoader = __importStar(require("../config/loader.js"));
|
|
47
|
+
(0, vitest_1.describe)("tracker CLI", () => {
|
|
48
|
+
(0, vitest_1.it)("sync-in without trackerId exits with a clear usage error", async () => {
|
|
49
|
+
const command = (0, tracker_js_1.createTrackerCommand)({ repoRoot: "/repo" });
|
|
50
|
+
const errorSpy = vitest_1.vi.spyOn(console, "error").mockImplementation(() => { });
|
|
51
|
+
const exitSpy = vitest_1.vi.spyOn(process, "exit").mockImplementation(((code) => {
|
|
52
|
+
throw new Error(`process.exit:${code}`);
|
|
53
|
+
}));
|
|
54
|
+
try {
|
|
55
|
+
await (0, vitest_1.expect)(command.parseAsync(["node", "tracker", "sync-in"], { from: "node" })).rejects.toThrow("process.exit:1");
|
|
56
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith("Error: trackerId is required (e.g., 'polaris tracker sync-in POL-198').");
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
exitSpy.mockRestore();
|
|
60
|
+
errorSpy.mockRestore();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.describe)("sync-in persistence", () => {
|
|
64
|
+
let tmpDir;
|
|
65
|
+
let consoleSpy;
|
|
66
|
+
let consoleLogSpy;
|
|
67
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
68
|
+
tmpDir = await (0, promises_1.mkdtemp)(node_path_1.default.join((0, node_os_1.tmpdir)(), "polaris-test-"));
|
|
69
|
+
consoleSpy = vitest_1.vi.spyOn(console, "error").mockImplementation(() => { });
|
|
70
|
+
consoleLogSpy = vitest_1.vi.spyOn(console, "log").mockImplementation(() => { });
|
|
71
|
+
});
|
|
72
|
+
(0, vitest_1.afterEach)(async () => {
|
|
73
|
+
consoleSpy.mockRestore();
|
|
74
|
+
consoleLogSpy.mockRestore();
|
|
75
|
+
await (0, promises_1.rm)(tmpDir, { recursive: true, force: true });
|
|
76
|
+
vitest_1.vi.restoreAllMocks();
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.it)("tracker sync-in POL-198 writes .polaris/clusters/POL-198/clusters.json", async () => {
|
|
79
|
+
const fakeGraph = {
|
|
80
|
+
schemaVersion: "v2",
|
|
81
|
+
source: { id: "POL-198", type: "Linear" },
|
|
82
|
+
nodes: {
|
|
83
|
+
"POL-198": { id: "POL-198", title: "Root issue", status: "Todo" },
|
|
84
|
+
},
|
|
85
|
+
dependencies: {},
|
|
86
|
+
clusters: {
|
|
87
|
+
"POL-198": { id: "POL-198", title: "Linear Issue: POL-198", children: ["POL-198"] },
|
|
88
|
+
},
|
|
89
|
+
activeCluster: "POL-198",
|
|
90
|
+
};
|
|
91
|
+
const fakeLocalGraph = local_graph_js_1.LocalGraph.fromGraph(fakeGraph);
|
|
92
|
+
vitest_1.vi.spyOn(linearModule.LinearAdapter.prototype, "syncIn").mockResolvedValue(fakeLocalGraph);
|
|
93
|
+
vitest_1.vi.spyOn(configLoader, "loadConfig").mockReturnValue({ tracker: { adapter: "linear", linear: { enabled: true } } });
|
|
94
|
+
const command = (0, tracker_js_1.createTrackerCommand)({ repoRoot: tmpDir });
|
|
95
|
+
await command.parseAsync(["node", "tracker", "sync-in", "POL-198"], { from: "node" });
|
|
96
|
+
const expectedPath = node_path_1.default.join(tmpDir, ".polaris", "clusters", "POL-198", "clusters.json");
|
|
97
|
+
const contents = await (0, promises_1.readFile)(expectedPath, "utf-8");
|
|
98
|
+
const parsed = JSON.parse(contents);
|
|
99
|
+
(0, vitest_1.expect)(parsed.schemaVersion).toBe("v2");
|
|
100
|
+
(0, vitest_1.expect)(parsed.activeCluster).toBe("POL-198");
|
|
101
|
+
(0, vitest_1.expect)(parsed.nodes["POL-198"]).toEqual({ id: "POL-198", title: "Root issue", status: "Todo" });
|
|
102
|
+
(0, vitest_1.expect)(consoleLogSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining("sync-in complete. Active cluster: POL-198"));
|
|
103
|
+
(0, vitest_1.expect)(consoleLogSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining(expectedPath));
|
|
104
|
+
});
|
|
105
|
+
(0, vitest_1.it)("tracker sync-in creates the cluster directory if it does not exist", async () => {
|
|
106
|
+
const fakeGraph = {
|
|
107
|
+
schemaVersion: "v2",
|
|
108
|
+
source: { id: "POL-999", type: "Linear" },
|
|
109
|
+
nodes: {},
|
|
110
|
+
dependencies: {},
|
|
111
|
+
clusters: {
|
|
112
|
+
"POL-999": { id: "POL-999", title: "Linear Issue: POL-999", children: [] },
|
|
113
|
+
},
|
|
114
|
+
activeCluster: "POL-999",
|
|
115
|
+
};
|
|
116
|
+
const fakeLocalGraph = local_graph_js_1.LocalGraph.fromGraph(fakeGraph);
|
|
117
|
+
vitest_1.vi.spyOn(linearModule.LinearAdapter.prototype, "syncIn").mockResolvedValue(fakeLocalGraph);
|
|
118
|
+
vitest_1.vi.spyOn(configLoader, "loadConfig").mockReturnValue({ tracker: { adapter: "linear", linear: { enabled: true } } });
|
|
119
|
+
const command = (0, tracker_js_1.createTrackerCommand)({ repoRoot: tmpDir });
|
|
120
|
+
await command.parseAsync(["node", "tracker", "sync-in", "POL-999"], { from: "node" });
|
|
121
|
+
const expectedPath = node_path_1.default.join(tmpDir, ".polaris", "clusters", "POL-999", "clusters.json");
|
|
122
|
+
const contents = await (0, promises_1.readFile)(expectedPath, "utf-8");
|
|
123
|
+
(0, vitest_1.expect)(JSON.parse(contents).schemaVersion).toBe("v2");
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|