@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,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Compact worker prompt builder.
|
|
4
|
+
*
|
|
5
|
+
* Generates deterministic, size-bounded prompts for impl worker dispatch.
|
|
6
|
+
* Replaces ad-hoc string construction in compileImplPacket with a structured
|
|
7
|
+
* template that omits full issue bodies, repeated doctrine, and architecture
|
|
8
|
+
* explanations — all of which inflate token cost without aiding implementation.
|
|
9
|
+
*
|
|
10
|
+
* Two modes:
|
|
11
|
+
* compact (default) — narrow single-repo children; structured template only.
|
|
12
|
+
* full — cross-cutting or architectural children; may include
|
|
13
|
+
* expanded issue context.
|
|
14
|
+
*
|
|
15
|
+
* Governance instructions (validation, commit, boundary, reporting) are always
|
|
16
|
+
* preserved in both modes.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.isNarrowChild = isNarrowChild;
|
|
20
|
+
exports.selectPromptMode = selectPromptMode;
|
|
21
|
+
exports.buildWorkerPrompt = buildWorkerPrompt;
|
|
22
|
+
exports.buildPromptFromPacketInput = buildPromptFromPacketInput;
|
|
23
|
+
// ── Narrow-child heuristics ───────────────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Labels that mark a child as non-narrow (requires full context).
|
|
26
|
+
* Checked against open_children_meta[childId].labels.
|
|
27
|
+
*/
|
|
28
|
+
const WIDE_LABELS = new Set([
|
|
29
|
+
'cross-cutting',
|
|
30
|
+
'high-risk',
|
|
31
|
+
'parallel',
|
|
32
|
+
'worker-isolation',
|
|
33
|
+
'architectural',
|
|
34
|
+
]);
|
|
35
|
+
/**
|
|
36
|
+
* Returns true when a child qualifies for compact dispatch.
|
|
37
|
+
* A child is narrow when it has no wide labels and no explicit full-context flag.
|
|
38
|
+
*/
|
|
39
|
+
function isNarrowChild(childId, state) {
|
|
40
|
+
const meta = state.open_children_meta?.[childId];
|
|
41
|
+
if (!meta)
|
|
42
|
+
return true;
|
|
43
|
+
const labels = meta.labels ?? [];
|
|
44
|
+
for (const label of labels) {
|
|
45
|
+
if (WIDE_LABELS.has(label))
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Selects the prompt mode for a given child.
|
|
52
|
+
* - Returns 'compact' for narrow children (default).
|
|
53
|
+
* - Returns 'full' when forced via override or when child is wide.
|
|
54
|
+
*/
|
|
55
|
+
function selectPromptMode(childId, state, override) {
|
|
56
|
+
if (override)
|
|
57
|
+
return override;
|
|
58
|
+
return isNarrowChild(childId, state) ? 'compact' : 'full';
|
|
59
|
+
}
|
|
60
|
+
// ── Builder ───────────────────────────────────────────────────────────────────
|
|
61
|
+
/**
|
|
62
|
+
* Build a compact or full worker dispatch prompt.
|
|
63
|
+
*
|
|
64
|
+
* The compact template carries only what the worker needs to implement:
|
|
65
|
+
* identity, location, goal, scope, acceptance criteria, helpers, validation,
|
|
66
|
+
* and reporting format. It intentionally omits full issue bodies, cluster JSON,
|
|
67
|
+
* repeated doctrine, and architecture explanations.
|
|
68
|
+
*
|
|
69
|
+
* Full mode appends expanded issue context after the compact body.
|
|
70
|
+
* Governance instructions are always present in both modes.
|
|
71
|
+
*/
|
|
72
|
+
function buildWorkerPrompt(input) {
|
|
73
|
+
const lines = [];
|
|
74
|
+
// ── Header ────────────────────────────────────────────────────────────────
|
|
75
|
+
lines.push(`Issue: ${input.issueId} — ${input.title}`);
|
|
76
|
+
lines.push(`Worktree: ${input.worktree}`);
|
|
77
|
+
lines.push(`Branch: ${input.branch}`);
|
|
78
|
+
lines.push('');
|
|
79
|
+
// ── Goal ──────────────────────────────────────────────────────────────────
|
|
80
|
+
lines.push('## Goal');
|
|
81
|
+
lines.push(input.goal.trim());
|
|
82
|
+
lines.push('');
|
|
83
|
+
// ── Scope ─────────────────────────────────────────────────────────────────
|
|
84
|
+
lines.push('## Scope');
|
|
85
|
+
if (input.scopeTouch.length > 0) {
|
|
86
|
+
lines.push('Touch only:');
|
|
87
|
+
for (const s of input.scopeTouch)
|
|
88
|
+
lines.push(`- ${s}`);
|
|
89
|
+
}
|
|
90
|
+
if (input.scopeAvoid.length > 0) {
|
|
91
|
+
lines.push('Do not touch:');
|
|
92
|
+
for (const s of input.scopeAvoid)
|
|
93
|
+
lines.push(`- ${s}`);
|
|
94
|
+
}
|
|
95
|
+
lines.push('');
|
|
96
|
+
// ── Acceptance Criteria ───────────────────────────────────────────────────
|
|
97
|
+
lines.push('## Acceptance Criteria');
|
|
98
|
+
for (const ac of input.acceptanceCriteria)
|
|
99
|
+
lines.push(`- ${ac}`);
|
|
100
|
+
lines.push('');
|
|
101
|
+
// ── Existing Helpers ──────────────────────────────────────────────────────
|
|
102
|
+
if (input.existingHelpers.length > 0) {
|
|
103
|
+
lines.push('## Existing Helpers');
|
|
104
|
+
for (const h of input.existingHelpers)
|
|
105
|
+
lines.push(`- ${h}`);
|
|
106
|
+
lines.push('');
|
|
107
|
+
}
|
|
108
|
+
// ── Validation ────────────────────────────────────────────────────────────
|
|
109
|
+
lines.push('## Validation');
|
|
110
|
+
for (const cmd of input.validationCommands)
|
|
111
|
+
lines.push(`- ${cmd}`);
|
|
112
|
+
lines.push('');
|
|
113
|
+
// ── Commit ────────────────────────────────────────────────────────────────
|
|
114
|
+
lines.push('## Commit');
|
|
115
|
+
lines.push(input.commitFormat);
|
|
116
|
+
lines.push('');
|
|
117
|
+
// ── State + telemetry (governance — always present) ───────────────────────
|
|
118
|
+
lines.push('## Governance');
|
|
119
|
+
lines.push(`- Do NOT modify open_children or completed_children in ${input.stateFile}. The parent runtime (loop continue) owns state transitions.`);
|
|
120
|
+
lines.push(`- Append a telemetry event to ${input.telemetryFile}.`);
|
|
121
|
+
lines.push('');
|
|
122
|
+
// ── Worker Heartbeat Telemetry (observability — always present) ────────────
|
|
123
|
+
lines.push('## Worker Progress Telemetry (MANDATORY)');
|
|
124
|
+
lines.push('The parent CANNOT see your work. You MUST emit heartbeat events so the parent knows you are alive and making progress.');
|
|
125
|
+
lines.push('');
|
|
126
|
+
lines.push(`After EVERY step, append a JSONL event to ${input.telemetryFile}:`);
|
|
127
|
+
lines.push('```jsonl');
|
|
128
|
+
lines.push(`{"event":"worker-heartbeat","run_id":"<from packet>","child_id":"${input.issueId}","step_cursor":"<current step>","timestamp":"<ISO8601>","progress_pct":<0-100>,"files_changed":<count>,"current_file":"<file being edited>"}`);
|
|
129
|
+
lines.push('```');
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push('Required heartbeat points:');
|
|
132
|
+
lines.push(' 1. Immediately after reading this packet (step_cursor: "start")');
|
|
133
|
+
lines.push(' 2. After verifying state file (step_cursor: "verify")');
|
|
134
|
+
lines.push(' 3. After EACH file edit (step_cursor: "implement")');
|
|
135
|
+
lines.push(' 4. After running validation (step_cursor: "validate")');
|
|
136
|
+
lines.push(' 5. After creating commit (step_cursor: "commit")');
|
|
137
|
+
lines.push(' 6. Before terminating (step_cursor: "complete" or "failed")');
|
|
138
|
+
lines.push('');
|
|
139
|
+
lines.push('If heartbeats stop, the parent will assume you crashed and may dispatch a replacement worker.');
|
|
140
|
+
lines.push('');
|
|
141
|
+
// ── Approval Escalation Telemetry ───────────────────────────────────────────
|
|
142
|
+
lines.push('## Approval Escalation (when uncertain)');
|
|
143
|
+
lines.push('You have a sealed packet defining your exact scope, allowed files, and validation commands. Use this to decide:');
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push('Rule 1 - Auto-approve WITHIN scope (normal work):');
|
|
146
|
+
lines.push(' - If the operation touches files within `instructions.allowed_scope` → Just do it');
|
|
147
|
+
lines.push(' - If the command is in `instructions.validation_commands` → Just run it');
|
|
148
|
+
lines.push(' - Low risk, expected work → No need to ask, emit heartbeat with step_cursor: "implement"');
|
|
149
|
+
lines.push('');
|
|
150
|
+
lines.push('Rule 2 - ESCALATE out-of-scope or high-risk:');
|
|
151
|
+
lines.push(' - File outside allowed_scope → Emit worker-blocked with approval_type: "out-of-scope"');
|
|
152
|
+
lines.push(' - Destructive operation (rm -rf, major refactor) → Emit worker-blocked with approval_type: "destructive"');
|
|
153
|
+
lines.push(' - External API calls with cost → Emit worker-blocked with approval_type: "cost"');
|
|
154
|
+
lines.push(' - Changing secrets/.env → Emit worker-blocked with approval_type: "security"');
|
|
155
|
+
lines.push(' - Unclear requirements → Emit worker-blocked with approval_type: "ambiguous"');
|
|
156
|
+
lines.push('');
|
|
157
|
+
lines.push('To escalate, emit IMMEDIATELY to telemetry:');
|
|
158
|
+
lines.push('```jsonl');
|
|
159
|
+
lines.push(`{"event":"worker-blocked","run_id":"<from packet>","child_id":"${input.issueId}","reason":"needs-approval","approval_type":"<out-of-scope|destructive|cost|security|ambiguous>","description":"<specifically what needs approval>","blocker_id":"<unique-id>","timestamp":"<ISO8601>"}`);
|
|
160
|
+
lines.push('```');
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push('Then: Continue heartbeats every 30s with step_cursor: "blocked-awaiting-approval"');
|
|
163
|
+
lines.push('Wait for parent response. If no response in 5 minutes → TERMINATE with approval-timeout.');
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push('Remember: Your packet scope is your authority. Within scope = proceed. Outside scope = escalate.');
|
|
166
|
+
lines.push('');
|
|
167
|
+
// ── Route cognition delta (always present) ────────────────────────────────
|
|
168
|
+
lines.push('## Route Cognition Delta');
|
|
169
|
+
lines.push('After implementation, apply route-local cognition delta — only if something materially changed.');
|
|
170
|
+
lines.push('');
|
|
171
|
+
lines.push('**POLARIS.md** — update only when ALL of the following are true:');
|
|
172
|
+
lines.push(' - You touched a file in that folder (not a distant folder).');
|
|
173
|
+
lines.push(' - The change materially affects: folder responsibilities, commands/workflows,');
|
|
174
|
+
lines.push(' execution constraints, ownership/routing, or operational behavior.');
|
|
175
|
+
lines.push(' - The current POLARIS.md content is actually wrong or incomplete as a result.');
|
|
176
|
+
lines.push(' DO NOT update POLARIS.md for: formatting fixes, comment changes, tiny refactors,');
|
|
177
|
+
lines.push(' internal implementation details, or any change that leaves the operational guidance');
|
|
178
|
+
lines.push(' still accurate. When in doubt, do not update.');
|
|
179
|
+
lines.push('');
|
|
180
|
+
lines.push('**SUMMARY.md** — update only when: linked docs/specs changed, canon relationships');
|
|
181
|
+
lines.push(' changed, architecture meaning changed, or doctrine/spec linkage changed.');
|
|
182
|
+
lines.push(' SUMMARY.md is informational only. Do not create it if missing — that is a hint for');
|
|
183
|
+
lines.push(' operators, not a task for workers. Keep it short. Never add operational doctrine.');
|
|
184
|
+
lines.push('');
|
|
185
|
+
lines.push('**Never** scan unrelated folders. **Never** regenerate all route docs.');
|
|
186
|
+
lines.push('If no material change occurred, skip this section entirely.');
|
|
187
|
+
lines.push('');
|
|
188
|
+
// ── Report Back ───────────────────────────────────────────────────────────
|
|
189
|
+
lines.push('## Report Back');
|
|
190
|
+
lines.push('- files changed');
|
|
191
|
+
lines.push('- validation results');
|
|
192
|
+
lines.push('- commit hash');
|
|
193
|
+
lines.push('- blockers');
|
|
194
|
+
lines.push('');
|
|
195
|
+
// ── Termination (governance — always present) ─────────────────────────────
|
|
196
|
+
lines.push('TERMINATE SESSION IMMEDIATELY. Do not select or execute the next child.');
|
|
197
|
+
// ── Full mode: append expanded context ───────────────────────────────────
|
|
198
|
+
if (input.mode === 'full' && input.issueContext) {
|
|
199
|
+
lines.push('');
|
|
200
|
+
lines.push('---');
|
|
201
|
+
lines.push('');
|
|
202
|
+
lines.push('## Expanded Issue Context');
|
|
203
|
+
lines.push(`**${input.issueContext.id}**: ${input.issueContext.title}`);
|
|
204
|
+
if (input.issueContext.body) {
|
|
205
|
+
lines.push('');
|
|
206
|
+
lines.push(input.issueContext.body);
|
|
207
|
+
}
|
|
208
|
+
if (input.issueContext.key_requirements.length > 0) {
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push('Key requirements:');
|
|
211
|
+
for (const [i, r] of input.issueContext.key_requirements.entries()) {
|
|
212
|
+
lines.push(`${i + 1}. ${r}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const prompt = lines.join('\n');
|
|
217
|
+
const charCount = prompt.length;
|
|
218
|
+
return {
|
|
219
|
+
prompt,
|
|
220
|
+
metrics: {
|
|
221
|
+
mode: input.mode,
|
|
222
|
+
char_count: charCount,
|
|
223
|
+
estimated_tokens: Math.round(charCount / 4),
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Build a worker prompt from the same inputs used by compileImplPacket.
|
|
229
|
+
* Derives goal, scope, acceptance criteria, and helpers from issue context.
|
|
230
|
+
*/
|
|
231
|
+
function buildPromptFromPacketInput(input) {
|
|
232
|
+
const requirements = input.issueContext?.key_requirements ?? [];
|
|
233
|
+
const body = input.issueContext?.body?.trim();
|
|
234
|
+
// Body is the canonical goal text — it is the full issue description written by the
|
|
235
|
+
// product team. Use it verbatim so the worker acts on the real spec, not a title stub.
|
|
236
|
+
// Fall back to first requirement, then to a minimal "Implement X" placeholder.
|
|
237
|
+
const goal = body
|
|
238
|
+
?? (requirements.length > 0 ? requirements[0] : `Implement ${input.issueId}: "${input.title}".`);
|
|
239
|
+
return buildWorkerPrompt({
|
|
240
|
+
issueId: input.issueId,
|
|
241
|
+
title: input.title,
|
|
242
|
+
worktree: input.worktree,
|
|
243
|
+
branch: input.branch,
|
|
244
|
+
goal,
|
|
245
|
+
scopeTouch: input.allowedScope ?? [],
|
|
246
|
+
scopeAvoid: [],
|
|
247
|
+
// When body is the goal, all requirements are acceptance criteria (none was consumed as goal).
|
|
248
|
+
// When requirements[0] is the goal, the rest (slice(1)) are acceptance criteria.
|
|
249
|
+
acceptanceCriteria: body
|
|
250
|
+
? requirements
|
|
251
|
+
: (requirements.length > 1 ? requirements.slice(1) : requirements),
|
|
252
|
+
existingHelpers: [],
|
|
253
|
+
validationCommands: input.validationCommands ?? [],
|
|
254
|
+
commitFormat: `[${input.issueId}] ${input.title}`,
|
|
255
|
+
stateFile: input.stateFile,
|
|
256
|
+
telemetryFile: input.telemetryFile,
|
|
257
|
+
issueContext: input.issueContext,
|
|
258
|
+
mode: input.mode,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for src/loop/worker-prompt.ts
|
|
4
|
+
*
|
|
5
|
+
* Covers:
|
|
6
|
+
* - compact prompt generation (structure, required sections, governance)
|
|
7
|
+
* - full mode: expanded issue context appended
|
|
8
|
+
* - narrow-child detection via labels
|
|
9
|
+
* - prompt mode selection
|
|
10
|
+
* - oversized requirement compression (many requirements still produce one prompt)
|
|
11
|
+
* - prompt metrics accuracy
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
const vitest_1 = require("vitest");
|
|
15
|
+
const worker_prompt_js_1 = require("./worker-prompt.js");
|
|
16
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
17
|
+
function makeState(labels = []) {
|
|
18
|
+
return {
|
|
19
|
+
schema_version: "1.0",
|
|
20
|
+
run_id: "test-run",
|
|
21
|
+
cluster_id: "POL-130",
|
|
22
|
+
skill: "polaris-run",
|
|
23
|
+
artifact_dir: ".taskchain_artifacts/polaris-run",
|
|
24
|
+
branch: "feat/test",
|
|
25
|
+
current_step_id: "03-select-child",
|
|
26
|
+
step_cursor: "dispatching",
|
|
27
|
+
status: "running",
|
|
28
|
+
session_type: "implementation",
|
|
29
|
+
active_child: "POL-131",
|
|
30
|
+
last_commit: "",
|
|
31
|
+
pr_url: "",
|
|
32
|
+
next_open_child: "POL-131",
|
|
33
|
+
completed_children: [],
|
|
34
|
+
open_children: ["POL-131"],
|
|
35
|
+
open_children_meta: {
|
|
36
|
+
"POL-131": {
|
|
37
|
+
title: "IMPLEMENT: Add .smartdocignore parser",
|
|
38
|
+
state: "Backlog",
|
|
39
|
+
status_type: "backlog",
|
|
40
|
+
blocked_by: [],
|
|
41
|
+
labels,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
context_budget: { children_completed: 0, files_touched_total: 0, last_child_files_touched: 0 },
|
|
45
|
+
validation_status: "not-run",
|
|
46
|
+
updated_at: new Date().toISOString(),
|
|
47
|
+
blocker: null,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function makeBaseInput(overrides = {}) {
|
|
51
|
+
return {
|
|
52
|
+
issueId: "POL-131",
|
|
53
|
+
title: "Add .smartdocignore parser",
|
|
54
|
+
worktree: "/repo",
|
|
55
|
+
branch: "feat/test",
|
|
56
|
+
goal: "Parse .smartdocignore and enforce it during docs ingest.",
|
|
57
|
+
scopeTouch: ["src/smartdocs-engine/ingest.ts", "src/smartdocs-engine/ignore-parser.ts"],
|
|
58
|
+
scopeAvoid: ["src/loop/", "src/finalize/"],
|
|
59
|
+
acceptanceCriteria: [
|
|
60
|
+
"Parser reads .smartdocignore from repo root",
|
|
61
|
+
"Ignored paths are skipped during ingest",
|
|
62
|
+
],
|
|
63
|
+
existingHelpers: ["src/utils/glob.ts — glob matching utilities"],
|
|
64
|
+
validationCommands: ["npm run build", "npm test"],
|
|
65
|
+
commitFormat: "[POL-131] Add .smartdocignore parser",
|
|
66
|
+
stateFile: ".taskchain_artifacts/polaris-run/current-state.json",
|
|
67
|
+
telemetryFile: ".taskchain_artifacts/polaris-run/runs/test/telemetry.jsonl",
|
|
68
|
+
mode: "compact",
|
|
69
|
+
...overrides,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
73
|
+
(0, vitest_1.describe)("buildWorkerPrompt", () => {
|
|
74
|
+
(0, vitest_1.it)("compact prompt contains required header fields", () => {
|
|
75
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
76
|
+
(0, vitest_1.expect)(prompt).toContain("Issue: POL-131 — Add .smartdocignore parser");
|
|
77
|
+
(0, vitest_1.expect)(prompt).toContain("Worktree: /repo");
|
|
78
|
+
(0, vitest_1.expect)(prompt).toContain("Branch: feat/test");
|
|
79
|
+
});
|
|
80
|
+
(0, vitest_1.it)("compact prompt contains all required sections", () => {
|
|
81
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
82
|
+
(0, vitest_1.expect)(prompt).toContain("## Goal");
|
|
83
|
+
(0, vitest_1.expect)(prompt).toContain("## Scope");
|
|
84
|
+
(0, vitest_1.expect)(prompt).toContain("## Acceptance Criteria");
|
|
85
|
+
(0, vitest_1.expect)(prompt).toContain("## Existing Helpers");
|
|
86
|
+
(0, vitest_1.expect)(prompt).toContain("## Validation");
|
|
87
|
+
(0, vitest_1.expect)(prompt).toContain("## Commit");
|
|
88
|
+
(0, vitest_1.expect)(prompt).toContain("## Governance");
|
|
89
|
+
(0, vitest_1.expect)(prompt).toContain("## Report Back");
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.it)("compact prompt contains governance instructions", () => {
|
|
92
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
93
|
+
(0, vitest_1.expect)(prompt).toContain("open_children to completed_children");
|
|
94
|
+
(0, vitest_1.expect)(prompt).toContain("telemetry.jsonl");
|
|
95
|
+
(0, vitest_1.expect)(prompt).toContain("TERMINATE SESSION IMMEDIATELY");
|
|
96
|
+
});
|
|
97
|
+
(0, vitest_1.it)("compact prompt contains report back fields", () => {
|
|
98
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
99
|
+
(0, vitest_1.expect)(prompt).toContain("files changed");
|
|
100
|
+
(0, vitest_1.expect)(prompt).toContain("validation results");
|
|
101
|
+
(0, vitest_1.expect)(prompt).toContain("commit hash");
|
|
102
|
+
(0, vitest_1.expect)(prompt).toContain("blockers");
|
|
103
|
+
});
|
|
104
|
+
(0, vitest_1.it)("compact prompt does NOT include expanded issue context section", () => {
|
|
105
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
106
|
+
(0, vitest_1.expect)(prompt).not.toContain("## Expanded Issue Context");
|
|
107
|
+
(0, vitest_1.expect)(prompt).not.toContain("---");
|
|
108
|
+
});
|
|
109
|
+
(0, vitest_1.it)("full mode appends expanded issue context", () => {
|
|
110
|
+
const input = makeBaseInput({
|
|
111
|
+
mode: "full",
|
|
112
|
+
issueContext: {
|
|
113
|
+
id: "POL-131",
|
|
114
|
+
title: "Add .smartdocignore parser",
|
|
115
|
+
key_requirements: ["Parse .smartdocignore", "Enforce during ingest"],
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(input);
|
|
119
|
+
(0, vitest_1.expect)(prompt).toContain("## Expanded Issue Context");
|
|
120
|
+
(0, vitest_1.expect)(prompt).toContain("Parse .smartdocignore");
|
|
121
|
+
(0, vitest_1.expect)(prompt).toContain("Enforce during ingest");
|
|
122
|
+
});
|
|
123
|
+
(0, vitest_1.it)("full mode without issueContext does not append expanded section", () => {
|
|
124
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput({ mode: "full" }));
|
|
125
|
+
(0, vitest_1.expect)(prompt).not.toContain("## Expanded Issue Context");
|
|
126
|
+
});
|
|
127
|
+
(0, vitest_1.it)("compact prompt is smaller than full prompt with context", () => {
|
|
128
|
+
const issueContext = {
|
|
129
|
+
id: "POL-131",
|
|
130
|
+
title: "Add .smartdocignore parser",
|
|
131
|
+
key_requirements: Array.from({ length: 10 }, (_, i) => `Requirement ${i + 1}`),
|
|
132
|
+
};
|
|
133
|
+
const compact = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput({ mode: "compact", issueContext }));
|
|
134
|
+
const full = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput({ mode: "full", issueContext }));
|
|
135
|
+
(0, vitest_1.expect)(compact.metrics.char_count).toBeLessThan(full.metrics.char_count);
|
|
136
|
+
});
|
|
137
|
+
(0, vitest_1.it)("omits Existing Helpers section when list is empty", () => {
|
|
138
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput({ existingHelpers: [] }));
|
|
139
|
+
(0, vitest_1.expect)(prompt).not.toContain("## Existing Helpers");
|
|
140
|
+
});
|
|
141
|
+
(0, vitest_1.it)("scope touch and avoid lines are included", () => {
|
|
142
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
143
|
+
(0, vitest_1.expect)(prompt).toContain("src/smartdocs-engine/ingest.ts");
|
|
144
|
+
(0, vitest_1.expect)(prompt).toContain("src/loop/");
|
|
145
|
+
});
|
|
146
|
+
(0, vitest_1.it)("metrics char_count matches prompt length", () => {
|
|
147
|
+
const { prompt, metrics } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
148
|
+
(0, vitest_1.expect)(metrics.char_count).toBe(prompt.length);
|
|
149
|
+
});
|
|
150
|
+
(0, vitest_1.it)("metrics estimated_tokens is approximately char_count / 4", () => {
|
|
151
|
+
const { prompt, metrics } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput());
|
|
152
|
+
(0, vitest_1.expect)(metrics.estimated_tokens).toBe(Math.round(prompt.length / 4));
|
|
153
|
+
});
|
|
154
|
+
(0, vitest_1.it)("many requirements still produce a single prompt (no truncation)", () => {
|
|
155
|
+
const acceptanceCriteria = Array.from({ length: 20 }, (_, i) => `AC ${i + 1}`);
|
|
156
|
+
const { prompt } = (0, worker_prompt_js_1.buildWorkerPrompt)(makeBaseInput({ acceptanceCriteria }));
|
|
157
|
+
for (let i = 1; i <= 20; i++) {
|
|
158
|
+
(0, vitest_1.expect)(prompt).toContain(`AC ${i}`);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
(0, vitest_1.describe)("isNarrowChild", () => {
|
|
163
|
+
(0, vitest_1.it)("returns true when child has no labels", () => {
|
|
164
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState())).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
(0, vitest_1.it)("returns true when child has irrelevant labels", () => {
|
|
167
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["implement", "docs"]))).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
(0, vitest_1.it)("returns false for cross-cutting label", () => {
|
|
170
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["cross-cutting"]))).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
(0, vitest_1.it)("returns false for high-risk label", () => {
|
|
173
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["high-risk"]))).toBe(false);
|
|
174
|
+
});
|
|
175
|
+
(0, vitest_1.it)("returns false for parallel label", () => {
|
|
176
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["parallel"]))).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
(0, vitest_1.it)("returns false for worker-isolation label", () => {
|
|
179
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["worker-isolation"]))).toBe(false);
|
|
180
|
+
});
|
|
181
|
+
(0, vitest_1.it)("returns false for architectural label", () => {
|
|
182
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-131", makeState(["architectural"]))).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
(0, vitest_1.it)("returns true when child has no meta entry", () => {
|
|
185
|
+
const state = makeState();
|
|
186
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.isNarrowChild)("POL-999", state)).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
(0, vitest_1.describe)("selectPromptMode", () => {
|
|
190
|
+
(0, vitest_1.it)("returns compact for narrow child with no override", () => {
|
|
191
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.selectPromptMode)("POL-131", makeState())).toBe("compact");
|
|
192
|
+
});
|
|
193
|
+
(0, vitest_1.it)("returns full for non-narrow child", () => {
|
|
194
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.selectPromptMode)("POL-131", makeState(["cross-cutting"]))).toBe("full");
|
|
195
|
+
});
|
|
196
|
+
(0, vitest_1.it)("override wins over narrow detection", () => {
|
|
197
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.selectPromptMode)("POL-131", makeState(), "full")).toBe("full");
|
|
198
|
+
});
|
|
199
|
+
(0, vitest_1.it)("override wins over non-narrow detection", () => {
|
|
200
|
+
(0, vitest_1.expect)((0, worker_prompt_js_1.selectPromptMode)("POL-131", makeState(["cross-cutting"]), "compact")).toBe("compact");
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
(0, vitest_1.describe)("buildPromptFromPacketInput", () => {
|
|
204
|
+
(0, vitest_1.it)("produces a prompt with the correct issue ID and title", () => {
|
|
205
|
+
const { prompt } = (0, worker_prompt_js_1.buildPromptFromPacketInput)({
|
|
206
|
+
issueId: "POL-131",
|
|
207
|
+
title: "Add .smartdocignore parser",
|
|
208
|
+
worktree: ".",
|
|
209
|
+
branch: "feat/test",
|
|
210
|
+
stateFile: "state.json",
|
|
211
|
+
telemetryFile: "telemetry.jsonl",
|
|
212
|
+
mode: "compact",
|
|
213
|
+
});
|
|
214
|
+
(0, vitest_1.expect)(prompt).toContain("Issue: POL-131 — Add .smartdocignore parser");
|
|
215
|
+
});
|
|
216
|
+
(0, vitest_1.it)("uses first requirement as goal when issueContext provided", () => {
|
|
217
|
+
const { prompt } = (0, worker_prompt_js_1.buildPromptFromPacketInput)({
|
|
218
|
+
issueId: "POL-131",
|
|
219
|
+
title: "Add .smartdocignore parser",
|
|
220
|
+
worktree: ".",
|
|
221
|
+
branch: "feat/test",
|
|
222
|
+
stateFile: "state.json",
|
|
223
|
+
telemetryFile: "telemetry.jsonl",
|
|
224
|
+
issueContext: {
|
|
225
|
+
id: "POL-131",
|
|
226
|
+
title: "Add .smartdocignore parser",
|
|
227
|
+
key_requirements: ["Parse .smartdocignore from repo root", "Enforce during ingest"],
|
|
228
|
+
},
|
|
229
|
+
mode: "compact",
|
|
230
|
+
});
|
|
231
|
+
(0, vitest_1.expect)(prompt).toContain("Parse .smartdocignore from repo root");
|
|
232
|
+
});
|
|
233
|
+
(0, vitest_1.it)("returns compact metrics by default for narrow input", () => {
|
|
234
|
+
const { metrics } = (0, worker_prompt_js_1.buildPromptFromPacketInput)({
|
|
235
|
+
issueId: "POL-131",
|
|
236
|
+
title: "Title",
|
|
237
|
+
worktree: ".",
|
|
238
|
+
branch: "main",
|
|
239
|
+
stateFile: "s.json",
|
|
240
|
+
telemetryFile: "t.jsonl",
|
|
241
|
+
mode: "compact",
|
|
242
|
+
});
|
|
243
|
+
(0, vitest_1.expect)(metrics.mode).toBe("compact");
|
|
244
|
+
(0, vitest_1.expect)(metrics.char_count).toBeGreaterThan(0);
|
|
245
|
+
(0, vitest_1.expect)(metrics.estimated_tokens).toBeGreaterThan(0);
|
|
246
|
+
});
|
|
247
|
+
});
|