supipowers 1.5.2 → 2.0.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 +14 -8
- package/bin/install.mjs +20 -5
- package/bin/install.ts +95 -0
- package/package.json +8 -4
- package/skills/context-mode/SKILL.md +17 -10
- package/skills/harness/SKILL.md +94 -0
- package/skills/ui-design/SKILL.md +63 -0
- package/skills/ui-design/sub-agent-templates/component-builder.md +29 -0
- package/skills/ui-design/sub-agent-templates/design-critic.md +46 -0
- package/skills/ui-design/sub-agent-templates/pencil/component-builder.md +29 -0
- package/skills/ui-design/sub-agent-templates/pencil/design-critic.md +42 -0
- package/skills/ui-design/sub-agent-templates/pencil/section-assembler.md +27 -0
- package/skills/ui-design/sub-agent-templates/section-assembler.md +27 -0
- package/skills/ultraplan-discover/SKILL.md +96 -0
- package/skills/ultraplan-intake/SKILL.md +89 -0
- package/skills/ultraplan-research/SKILL.md +129 -0
- package/skills/ultraplan-review/SKILL.md +86 -0
- package/skills/ultraplan-review-scope/SKILL.md +111 -0
- package/skills/ultraplan-review-structure/SKILL.md +120 -0
- package/skills/ultraplan-review-tdd/SKILL.md +142 -0
- package/skills/ultraplan-scout/SKILL.md +110 -0
- package/skills/ultraplan-synthesize/SKILL.md +124 -0
- package/src/{quality/ai-session.ts → ai/final-message.ts} +27 -0
- package/src/ai/schema-text.ts +129 -0
- package/src/ai/structured-output.ts +274 -0
- package/src/ai/template.ts +27 -0
- package/src/bootstrap.ts +63 -28
- package/src/commands/agents.ts +149 -45
- package/src/commands/ai-review.ts +251 -30
- package/src/commands/clear.ts +434 -0
- package/src/commands/commit.ts +1 -0
- package/src/commands/config.ts +242 -44
- package/src/commands/context.ts +55 -28
- package/src/commands/doctor.ts +234 -6
- package/src/commands/fix-pr.ts +306 -131
- package/src/commands/generate.ts +111 -21
- package/src/commands/memory.ts +192 -0
- package/src/commands/model-picker.ts +28 -21
- package/src/commands/model.ts +19 -9
- package/src/commands/optimize-context.ts +408 -29
- package/src/commands/plan.ts +2 -0
- package/src/commands/qa.ts +312 -137
- package/src/commands/release.ts +259 -76
- package/src/commands/review.ts +293 -59
- package/src/commands/status.ts +200 -13
- package/src/commands/supi.ts +3 -35
- package/src/commands/ui-design.ts +394 -0
- package/src/commands/ultraplan.ts +1518 -0
- package/src/commands/update.ts +86 -0
- package/src/config/defaults.ts +62 -0
- package/src/config/loader.ts +448 -60
- package/src/config/schema.ts +108 -2
- package/src/context/optimizer.ts +25 -33
- package/src/context/rule-renderer.ts +223 -0
- package/src/context/savings.ts +258 -0
- package/src/context/startup-check.ts +380 -0
- package/src/context/startup-optimizer.ts +355 -0
- package/src/context/tokenignore.ts +146 -0
- package/src/context-mode/cache-handle.ts +49 -0
- package/src/context-mode/cache-preview.ts +71 -0
- package/src/context-mode/cache-store.ts +738 -0
- package/src/context-mode/compressor.ts +131 -26
- package/src/context-mode/dedup.ts +108 -0
- package/src/context-mode/detector.ts +35 -4
- package/src/context-mode/event-extractor.ts +14 -12
- package/src/context-mode/event-store.ts +91 -36
- package/src/context-mode/hooks.ts +798 -56
- package/src/context-mode/knowledge/store.ts +255 -11
- package/src/context-mode/memory-store.ts +325 -0
- package/src/context-mode/metrics-recorder.ts +158 -0
- package/src/context-mode/metrics-store.ts +765 -0
- package/src/context-mode/model.ts +24 -0
- package/src/context-mode/processor-keys.ts +29 -0
- package/src/context-mode/processors/build.ts +66 -0
- package/src/context-mode/processors/docker.ts +57 -0
- package/src/context-mode/processors/git.ts +111 -0
- package/src/context-mode/processors/json.ts +112 -0
- package/src/context-mode/processors/k8s.ts +67 -0
- package/src/context-mode/processors/lint.ts +67 -0
- package/src/context-mode/processors/log.ts +86 -0
- package/src/context-mode/processors/registry.ts +116 -0
- package/src/context-mode/processors/test-runner.ts +102 -0
- package/src/context-mode/processors/types.ts +20 -0
- package/src/context-mode/repomap.ts +400 -0
- package/src/context-mode/routing.ts +97 -24
- package/src/context-mode/sandbox/runners.ts +5 -1
- package/src/context-mode/snapshot-builder.ts +106 -11
- package/src/context-mode/source-hash.ts +173 -0
- package/src/context-mode/tool-name.ts +11 -0
- package/src/context-mode/tools.ts +654 -22
- package/src/context-mode/web/fetcher.ts +31 -12
- package/src/debug/logger.ts +2 -1
- package/src/deps/registry.ts +1 -1
- package/src/discipline/failure-summarizer.ts +170 -0
- package/src/discipline/failure-taxonomy.ts +131 -0
- package/src/discipline/workflow-invariants.ts +125 -0
- package/src/discovery/index.ts +31 -0
- package/src/discovery/lsp.ts +87 -0
- package/src/discovery/rank.ts +144 -0
- package/src/discovery/sources.ts +89 -0
- package/src/discovery/workflow.ts +87 -0
- package/src/docs/contracts.ts +39 -0
- package/src/docs/drift.ts +117 -87
- package/src/fix-pr/assessment.ts +200 -0
- package/src/fix-pr/contracts.ts +47 -0
- package/src/fix-pr/fetch-comments.ts +80 -0
- package/src/fix-pr/prompt-builder.ts +58 -40
- package/src/fix-pr/scripts/exec.ts +34 -0
- package/src/fix-pr/scripts/trigger-review.ts +106 -0
- package/src/fix-pr/scripts/wait-and-check.ts +108 -0
- package/src/fix-pr/types.ts +4 -0
- package/src/git/branch-finish.ts +5 -0
- package/src/git/commit-contract.ts +83 -0
- package/src/git/commit.ts +121 -184
- package/src/git/status.ts +62 -8
- package/src/harness/anti_slop/architecture-parser.ts +210 -0
- package/src/harness/anti_slop/backend-factory.ts +30 -0
- package/src/harness/anti_slop/backend.ts +140 -0
- package/src/harness/anti_slop/desloppify-adapter.ts +319 -0
- package/src/harness/anti_slop/fallow-adapter.ts +305 -0
- package/src/harness/anti_slop/installer.ts +227 -0
- package/src/harness/anti_slop/queue.ts +216 -0
- package/src/harness/anti_slop/recommend.ts +84 -0
- package/src/harness/anti_slop/score.ts +180 -0
- package/src/harness/anti_slop/synthetic-edit-test.ts +128 -0
- package/src/harness/artifacts/agents-md.ts +88 -0
- package/src/harness/artifacts/checks-wiring.ts +57 -0
- package/src/harness/artifacts/docs-tree.ts +79 -0
- package/src/harness/artifacts/lint-configs.ts +136 -0
- package/src/harness/artifacts/review-agents.ts +67 -0
- package/src/harness/bare-entry.ts +108 -0
- package/src/harness/command.ts +1010 -0
- package/src/harness/default-agents/design.md +23 -0
- package/src/harness/default-agents/discover.md +18 -0
- package/src/harness/default-agents/implement.md +24 -0
- package/src/harness/default-agents/plan.md +19 -0
- package/src/harness/default-agents/research.md +21 -0
- package/src/harness/default-agents/validate.md +22 -0
- package/src/harness/gc/reporter.ts +28 -0
- package/src/harness/gc/runner.ts +136 -0
- package/src/harness/hooks/layer-context-inject.ts +155 -0
- package/src/harness/hooks/post-session-sweep.ts +130 -0
- package/src/harness/hooks/pre-edit-dupe-probe.ts +224 -0
- package/src/harness/hooks/register.ts +118 -0
- package/src/harness/model.ts +117 -0
- package/src/harness/pipeline.ts +348 -0
- package/src/harness/project-paths.ts +235 -0
- package/src/harness/stage-runner.ts +107 -0
- package/src/harness/stages/design.ts +386 -0
- package/src/harness/stages/discover.ts +454 -0
- package/src/harness/stages/implement.ts +162 -0
- package/src/harness/stages/plan.ts +335 -0
- package/src/harness/stages/research.ts +263 -0
- package/src/harness/stages/validate.ts +684 -0
- package/src/harness/storage.ts +467 -0
- package/src/harness/tools.ts +426 -0
- package/src/lsp/bridge.ts +56 -95
- package/src/lsp/capabilities.ts +108 -0
- package/src/lsp/contracts.ts +35 -0
- package/src/lsp/detector.ts +8 -12
- package/src/markdown-frontmatter.ts +68 -0
- package/src/mempalace/bridge.ts +129 -0
- package/src/mempalace/config.ts +75 -0
- package/src/mempalace/format.ts +163 -0
- package/src/mempalace/hooks.ts +370 -0
- package/src/mempalace/installer-helper.ts +194 -0
- package/src/mempalace/python/mempalace_bridge.py +440 -0
- package/src/mempalace/runtime.ts +565 -0
- package/src/mempalace/schema.ts +264 -0
- package/src/mempalace/session-summary.ts +198 -0
- package/src/mempalace/tool.ts +186 -0
- package/src/mempalace/uv.ts +256 -0
- package/src/migrate/runner.ts +354 -0
- package/src/planning/approval-flow.ts +206 -9
- package/src/planning/plan-writer-prompt.ts +4 -3
- package/src/planning/planning-ask-tool.ts +39 -0
- package/src/planning/render-markdown.ts +74 -0
- package/src/planning/spec.ts +42 -0
- package/src/planning/system-prompt.ts +11 -8
- package/src/planning/validate.ts +84 -0
- package/src/platform/omp.ts +15 -2
- package/src/platform/system-prompt.ts +37 -0
- package/src/platform/test-utils.ts +3 -0
- package/src/platform/types.ts +6 -1
- package/src/qa/config.ts +12 -6
- package/src/qa/detect-app-type.ts +13 -6
- package/src/qa/matrix.ts +12 -6
- package/src/qa/prompt-builder.ts +28 -30
- package/src/qa/scripts/dev-server-utils.ts +72 -0
- package/src/qa/scripts/run-e2e-tests.ts +226 -0
- package/src/qa/scripts/start-dev-server.ts +138 -0
- package/src/qa/scripts/stop-dev-server.ts +77 -0
- package/src/qa/session.ts +13 -7
- package/src/quality/ai-setup.ts +27 -25
- package/src/quality/contracts.ts +34 -0
- package/src/quality/gates/ai-review.ts +20 -58
- package/src/quality/gates/command.ts +249 -46
- package/src/quality/review-gates.ts +18 -2
- package/src/quality/runner.ts +63 -22
- package/src/quality/schemas.ts +37 -2
- package/src/quality/setup.ts +96 -16
- package/src/release/changelog.ts +1 -1
- package/src/release/channels/custom.ts +13 -3
- package/src/release/channels/types.ts +5 -0
- package/src/release/contracts.ts +90 -0
- package/src/release/executor.ts +122 -45
- package/src/release/prompt.ts +18 -2
- package/src/release/targets.ts +86 -0
- package/src/release/version.ts +96 -71
- package/src/review/agent-loader.ts +298 -127
- package/src/review/fixer.ts +10 -6
- package/src/review/multi-agent-runner.ts +115 -14
- package/src/review/output.ts +12 -139
- package/src/review/runner.ts +12 -6
- package/src/review/scope.ts +144 -24
- package/src/review/types.ts +11 -20
- package/src/review/validator.ts +12 -6
- package/src/storage/fix-pr-sessions.ts +21 -14
- package/src/storage/plans.ts +14 -5
- package/src/storage/qa-sessions.ts +25 -19
- package/src/storage/reliability-metrics.ts +180 -0
- package/src/storage/reports.ts +8 -7
- package/src/storage/review-sessions.ts +55 -20
- package/src/tool-catalog/active-tool-controller.ts +164 -0
- package/src/tool-catalog/active-tool-planner.ts +212 -0
- package/src/tool-catalog/tool-groups.ts +102 -0
- package/src/types.ts +1401 -5
- package/src/ui-design/backend-adapter.ts +78 -0
- package/src/ui-design/backends/local-html.ts +82 -0
- package/src/ui-design/backends/pencil-mcp.ts +111 -0
- package/src/ui-design/components-scanner.ts +124 -0
- package/src/ui-design/config.ts +55 -0
- package/src/ui-design/pen-scanner.ts +95 -0
- package/src/ui-design/pen-selector.ts +72 -0
- package/src/ui-design/prompt-builder.ts +73 -0
- package/src/ui-design/scanner.ts +136 -0
- package/src/ui-design/session.ts +974 -0
- package/src/ui-design/system-prompt.ts +312 -0
- package/src/ui-design/tokens-scanner.ts +181 -0
- package/src/ui-design/types.ts +96 -0
- package/src/ultraplan/agent-catalog.ts +522 -0
- package/src/ultraplan/authoring/agent-catalog.ts +310 -0
- package/src/ultraplan/authoring/authoring-tools.ts +552 -0
- package/src/ultraplan/authoring/command-handlers.ts +339 -0
- package/src/ultraplan/authoring/markdown.ts +510 -0
- package/src/ultraplan/authoring/model.ts +162 -0
- package/src/ultraplan/authoring/pipeline.ts +319 -0
- package/src/ultraplan/authoring/stage-runner.ts +141 -0
- package/src/ultraplan/authoring/stages/approve.ts +249 -0
- package/src/ultraplan/authoring/stages/discover.ts +289 -0
- package/src/ultraplan/authoring/stages/intake.ts +203 -0
- package/src/ultraplan/authoring/stages/research.ts +399 -0
- package/src/ultraplan/authoring/stages/review.ts +333 -0
- package/src/ultraplan/authoring/stages/scout.ts +188 -0
- package/src/ultraplan/authoring/stages/synthesize.ts +348 -0
- package/src/ultraplan/authoring/storage.ts +594 -0
- package/src/ultraplan/authoring/synth-gate.ts +165 -0
- package/src/ultraplan/authoring-draft.ts +653 -0
- package/src/ultraplan/authoring-persist.ts +180 -0
- package/src/ultraplan/authoring-tool.ts +608 -0
- package/src/ultraplan/authoring-wizard.ts +587 -0
- package/src/ultraplan/batch/merge.ts +98 -0
- package/src/ultraplan/batch/planner.ts +150 -0
- package/src/ultraplan/batch/presenter.ts +97 -0
- package/src/ultraplan/batch/storage.ts +420 -0
- package/src/ultraplan/batch/supervisor.ts +317 -0
- package/src/ultraplan/batch/worker.ts +26 -0
- package/src/ultraplan/batch/worktree.ts +110 -0
- package/src/ultraplan/contracts.ts +1593 -0
- package/src/ultraplan/default-agents/authoring/discoverer.md +12 -0
- package/src/ultraplan/default-agents/authoring/intake.md +12 -0
- package/src/ultraplan/default-agents/authoring/planner.md +12 -0
- package/src/ultraplan/default-agents/authoring/researcher.md +12 -0
- package/src/ultraplan/default-agents/authoring/scope-checker.md +12 -0
- package/src/ultraplan/default-agents/authoring/scout.md +12 -0
- package/src/ultraplan/default-agents/authoring/structure-checker.md +12 -0
- package/src/ultraplan/default-agents/authoring/tdd-checker.md +12 -0
- package/src/ultraplan/default-agents/backend-domain-reviewer.md +10 -0
- package/src/ultraplan/default-agents/backend-executor.md +10 -0
- package/src/ultraplan/default-agents/backend-stack-reviewer.md +10 -0
- package/src/ultraplan/default-agents/backend-tester.md +10 -0
- package/src/ultraplan/default-agents/frontend-domain-reviewer.md +10 -0
- package/src/ultraplan/default-agents/frontend-executor.md +10 -0
- package/src/ultraplan/default-agents/frontend-stack-reviewer.md +10 -0
- package/src/ultraplan/default-agents/frontend-tester.md +10 -0
- package/src/ultraplan/default-agents/infrastructure-domain-reviewer.md +10 -0
- package/src/ultraplan/default-agents/infrastructure-executor.md +10 -0
- package/src/ultraplan/default-agents/infrastructure-stack-reviewer.md +10 -0
- package/src/ultraplan/default-agents/infrastructure-tester.md +10 -0
- package/src/ultraplan/execution/contract.ts +71 -0
- package/src/ultraplan/execution/policy.ts +217 -0
- package/src/ultraplan/execution/runtime-tools.ts +107 -0
- package/src/ultraplan/execution/session-runner.ts +281 -0
- package/src/ultraplan/next-router.ts +85 -0
- package/src/ultraplan/presenter.ts +359 -0
- package/src/ultraplan/project-paths.ts +342 -0
- package/src/ultraplan/runtime/active-execution.ts +72 -0
- package/src/ultraplan/runtime/apply-mutation.ts +416 -0
- package/src/ultraplan/runtime/blockers.ts +243 -0
- package/src/ultraplan/runtime/hook-bridge.ts +486 -0
- package/src/ultraplan/runtime/launch-context.ts +207 -0
- package/src/ultraplan/runtime/migration.ts +524 -0
- package/src/ultraplan/runtime/normalize.ts +281 -0
- package/src/ultraplan/runtime/proof.ts +260 -0
- package/src/ultraplan/runtime/reducer.ts +416 -0
- package/src/ultraplan/runtime/repair.ts +251 -0
- package/src/ultraplan/runtime/tracker-storage.ts +368 -0
- package/src/ultraplan/session-selection.ts +291 -0
- package/src/ultraplan/storage.ts +374 -0
- package/src/utils/editor.ts +38 -0
- package/src/utils/executable.ts +80 -0
- package/src/utils/paths.ts +1 -20
- package/src/utils/shell.ts +31 -0
- package/src/visual/companion.ts +2 -1
- package/src/visual/scripts/frame-template.html +60 -0
- package/src/visual/scripts/index.js +59 -13
- package/src/visual/scripts/package.json +3 -0
- package/src/visual/start-server.ts +2 -1
- package/src/workspace/git-scope.ts +64 -0
- package/src/workspace/locks.ts +23 -0
- package/src/workspace/package-manager.ts +117 -0
- package/src/workspace/path-mapping.ts +75 -0
- package/src/workspace/project-slug.ts +92 -0
- package/src/workspace/repo-root.ts +137 -0
- package/src/workspace/selector.ts +115 -0
- package/src/workspace/state-paths.ts +118 -0
- package/src/workspace/targets.ts +313 -0
- package/src/fix-pr/scripts/diff-comments.sh +0 -33
- package/src/fix-pr/scripts/fetch-pr-comments.sh +0 -25
- package/src/fix-pr/scripts/trigger-review.sh +0 -36
- package/src/fix-pr/scripts/wait-and-check.sh +0 -37
- package/src/qa/scripts/detect-app-type.sh +0 -68
- package/src/qa/scripts/discover-routes.sh +0 -143
- package/src/qa/scripts/run-e2e-tests.sh +0 -131
- package/src/qa/scripts/start-dev-server.sh +0 -46
- package/src/qa/scripts/stop-dev-server.sh +0 -36
- package/src/review/prompts/fix-output-schema.md +0 -18
- package/src/review/prompts/review-output-schema.md +0 -38
- package/src/review/template.ts +0 -15
- /package/src/{review → ai}/prompts/invalid-output-retry.md +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
UltraPlanAuthoringPipelineEvent,
|
|
3
|
+
UltraPlanAuthoringStage,
|
|
4
|
+
UltraPlanAuthoringState,
|
|
5
|
+
UltraPlanAuthoredArtifact,
|
|
6
|
+
UltraPlanBlocker,
|
|
7
|
+
UltraPlanSessionSummary,
|
|
8
|
+
UltraPlanStack,
|
|
9
|
+
} from "../types.js";
|
|
10
|
+
import type { UltraPlanRunOutcome } from "./execution/session-runner.js";
|
|
11
|
+
import type { UltraPlanSessionRecommendation } from "./next-router.js";
|
|
12
|
+
import {
|
|
13
|
+
isDraftReadyToPersist,
|
|
14
|
+
type UltraPlanAuthoredDraft,
|
|
15
|
+
} from "./authoring-draft.js";
|
|
16
|
+
import {
|
|
17
|
+
getUltraPlanIdleReasonLabel,
|
|
18
|
+
resolveUltraPlanSessionBucket,
|
|
19
|
+
type UltraPlanResolvedCursor,
|
|
20
|
+
type UltraPlanVisibleSession,
|
|
21
|
+
} from "./session-selection.js";
|
|
22
|
+
|
|
23
|
+
export interface UltraPlanPickerOption {
|
|
24
|
+
value: string;
|
|
25
|
+
label: string;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function buildUltraPlanPickerOptions(
|
|
30
|
+
sessions: UltraPlanVisibleSession[],
|
|
31
|
+
recommendations?: ReadonlyMap<string, UltraPlanSessionRecommendation>,
|
|
32
|
+
): UltraPlanPickerOption[] {
|
|
33
|
+
return sessions.map((session) => ({
|
|
34
|
+
value: session.sessionId,
|
|
35
|
+
label: `[${session.bucket}] ${formatInlineSessionTitle(session.title)}`,
|
|
36
|
+
description: describePickerDescription(session, recommendations?.get(session.sessionId)),
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function formatInlineSessionTitle(title: string): string {
|
|
41
|
+
return title
|
|
42
|
+
.replace(/[\u0000-\u001F\u007F]+/g, " ")
|
|
43
|
+
.replace(/\s+/g, " ")
|
|
44
|
+
.trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function describePickerDescription(
|
|
48
|
+
session: UltraPlanVisibleSession,
|
|
49
|
+
recommendation?: UltraPlanSessionRecommendation,
|
|
50
|
+
): string {
|
|
51
|
+
const base = describePickerSession(session);
|
|
52
|
+
if (!recommendation) return base;
|
|
53
|
+
return `${describePickerRecommendation(recommendation)} — ${base}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function describePickerSession(session: UltraPlanVisibleSession): string {
|
|
57
|
+
if (isSlice2SurfacedBlocker(session.blocker)) {
|
|
58
|
+
const idle = session.idleReasonLabel ?? `Blocked: ${session.blocker.message}`;
|
|
59
|
+
return `${idle} — ${session.blocker.code} (${session.blocker.recoveryMode})`;
|
|
60
|
+
}
|
|
61
|
+
if (session.idleReasonLabel) return `Idle: ${session.idleReasonLabel}`;
|
|
62
|
+
return `Current: ${session.cursor?.summary ?? "No active cursor"}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function renderUltraPlanRecommendationSummary(
|
|
66
|
+
recommendation: UltraPlanSessionRecommendation,
|
|
67
|
+
): string {
|
|
68
|
+
return `Recommended next: ${formatInlineSessionTitle(recommendation.session.title)} — ${describeRecommendationSummary(recommendation)}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function renderUltraPlanRecommendationStatusLine(
|
|
72
|
+
recommendation: UltraPlanSessionRecommendation,
|
|
73
|
+
): string {
|
|
74
|
+
return `Ultraplan next: ${formatInlineSessionTitle(recommendation.session.title)} — ${describeRecommendationStatus(recommendation)}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function describePickerRecommendation(
|
|
78
|
+
recommendation: UltraPlanSessionRecommendation,
|
|
79
|
+
): string {
|
|
80
|
+
switch (recommendation.reasonCode) {
|
|
81
|
+
case "ongoing":
|
|
82
|
+
return "Recommended next to run";
|
|
83
|
+
case "pending":
|
|
84
|
+
return "Ready to run";
|
|
85
|
+
case "awaiting-user":
|
|
86
|
+
case "mismatch":
|
|
87
|
+
return "Inspect before running";
|
|
88
|
+
case "blocked-manual":
|
|
89
|
+
return "Action needed";
|
|
90
|
+
case "blocked":
|
|
91
|
+
return "Blocked";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function describeRecommendationSummary(
|
|
96
|
+
recommendation: UltraPlanSessionRecommendation,
|
|
97
|
+
): string {
|
|
98
|
+
switch (recommendation.reasonCode) {
|
|
99
|
+
case "ongoing":
|
|
100
|
+
return "resume the in-progress session.";
|
|
101
|
+
case "pending":
|
|
102
|
+
return "ready to run.";
|
|
103
|
+
case "awaiting-user":
|
|
104
|
+
return "inspect it first; user input is required.";
|
|
105
|
+
case "blocked-manual":
|
|
106
|
+
return "action needed before it can resume.";
|
|
107
|
+
case "blocked":
|
|
108
|
+
return "inspect it first; it is blocked.";
|
|
109
|
+
case "mismatch":
|
|
110
|
+
return "inspect it first; session state is inconsistent.";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function describeRecommendationStatus(
|
|
115
|
+
recommendation: UltraPlanSessionRecommendation,
|
|
116
|
+
): string {
|
|
117
|
+
switch (recommendation.reasonCode) {
|
|
118
|
+
case "ongoing":
|
|
119
|
+
return "resume now";
|
|
120
|
+
case "pending":
|
|
121
|
+
return "ready to run";
|
|
122
|
+
case "awaiting-user":
|
|
123
|
+
return "waiting for user input";
|
|
124
|
+
case "blocked-manual":
|
|
125
|
+
return "action needed";
|
|
126
|
+
case "blocked":
|
|
127
|
+
return "blocked";
|
|
128
|
+
case "mismatch":
|
|
129
|
+
return "inspect session";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function renderUltraPlanStatus(
|
|
134
|
+
session: UltraPlanSessionSummary,
|
|
135
|
+
authored: UltraPlanAuthoredArtifact,
|
|
136
|
+
resolved: UltraPlanResolvedCursor,
|
|
137
|
+
): string {
|
|
138
|
+
const bucket = resolveUltraPlanSessionBucket(session, resolved);
|
|
139
|
+
const idleReason = getUltraPlanIdleReasonLabel(session);
|
|
140
|
+
const stackProgress = session.stacks.length > 0
|
|
141
|
+
? session.stacks.map((stack) => `${stack.stack} ${stack.terminalDomainCount}/${stack.domainCount} domains terminal`).join("; ")
|
|
142
|
+
: "—";
|
|
143
|
+
const domainProgress = formatDomainProgress(authored, resolved);
|
|
144
|
+
|
|
145
|
+
const lines = [
|
|
146
|
+
`Title: ${session.title}`,
|
|
147
|
+
`Goal: ${authored.goal}`,
|
|
148
|
+
`State: ${session.state}`,
|
|
149
|
+
`Bucket: ${bucket}`,
|
|
150
|
+
`Current: ${resolved.cursor.summary}`,
|
|
151
|
+
`Current source: ${resolved.source}`,
|
|
152
|
+
`Last completed (persisted): ${session.lastCompleted?.summary ?? "—"}`,
|
|
153
|
+
`Stack progress (persisted): ${stackProgress}`,
|
|
154
|
+
`Domain progress: ${domainProgress}`,
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
if (idleReason) {
|
|
158
|
+
lines.push(`Idle reason: ${idleReason}`);
|
|
159
|
+
}
|
|
160
|
+
if (isSlice2SurfacedBlocker(session.blocker)) {
|
|
161
|
+
lines.push(`Blocker: ${session.blocker.code}`);
|
|
162
|
+
lines.push(`Recovery: ${session.blocker.recoveryMode}`);
|
|
163
|
+
lines.push(`Next action: ${session.blocker.nextAction}`);
|
|
164
|
+
} else if (!idleReason && resolved.cursor.targetType === "session" && resolved.cursor.status === "complete") {
|
|
165
|
+
lines.push("Next action: None — session complete");
|
|
166
|
+
} else if (!idleReason) {
|
|
167
|
+
lines.push(`Next action: Resume ${resolved.cursor.summary}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return lines.join("\n");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function renderUltraPlanRunOutcome(outcome: UltraPlanRunOutcome): string {
|
|
174
|
+
if (outcome.kind === "completed") {
|
|
175
|
+
return [
|
|
176
|
+
`Completed: ${outcome.session.title}`,
|
|
177
|
+
`Current: ${outcome.session.cursor?.summary ?? "Session complete"}`,
|
|
178
|
+
].join("\n");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const blockerMessage = outcome.session.blocker?.message
|
|
182
|
+
?? outcome.session.cursor?.summary
|
|
183
|
+
?? "Paused";
|
|
184
|
+
const prefix = outcome.session.state === "awaiting-user" ? "Awaiting user" : "Paused";
|
|
185
|
+
|
|
186
|
+
return [
|
|
187
|
+
`${prefix}: ${outcome.session.title}`,
|
|
188
|
+
blockerMessage,
|
|
189
|
+
].join("\n");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function formatDomainProgress(authored: UltraPlanAuthoredArtifact, resolved: UltraPlanResolvedCursor): string {
|
|
193
|
+
const stackId = resolved.cursor.stack;
|
|
194
|
+
const domainId = resolved.cursor.domainId;
|
|
195
|
+
if (!stackId || !domainId) {
|
|
196
|
+
return "—";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const stack = authored.stacks.find((candidate) => candidate.stack === stackId);
|
|
200
|
+
const domain = stack?.domains.find((candidate) => candidate.id === domainId);
|
|
201
|
+
if (!domain) {
|
|
202
|
+
return "—";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const scenarios = [...domain.unit, ...domain.integration, ...domain.e2e];
|
|
206
|
+
const terminalCount = scenarios.filter((scenario) =>
|
|
207
|
+
scenario.status === "green-proved"
|
|
208
|
+
|| scenario.status === "review-passed"
|
|
209
|
+
|| scenario.status === "done").length;
|
|
210
|
+
|
|
211
|
+
return `${domain.id} ${terminalCount}/${scenarios.length} scenarios terminal`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const SLICE_2_SURFACED_BLOCKER_CODES: readonly string[] = [
|
|
215
|
+
"migration-unsafe",
|
|
216
|
+
"migration-conflict",
|
|
217
|
+
"interrupted-attempt",
|
|
218
|
+
];
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Slice-2 migration and interrupted-attempt blockers carry recovery metadata (recoveryMode,
|
|
222
|
+
* nextAction) that the picker and status surfaces must expose. Other blockers (legacy
|
|
223
|
+
* session-level codes) continue to use the generic idle-reason path.
|
|
224
|
+
*/
|
|
225
|
+
function isSlice2SurfacedBlocker(blocker: UltraPlanBlocker | null): blocker is UltraPlanBlocker {
|
|
226
|
+
return blocker !== null && SLICE_2_SURFACED_BLOCKER_CODES.includes(blocker.code);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function renderUltraPlanAuthoredDraft(draft: UltraPlanAuthoredDraft): string[] {
|
|
230
|
+
const lines: string[] = [
|
|
231
|
+
`Session: ${draft.title}`,
|
|
232
|
+
`Goal: ${draft.goal}`,
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
for (const stack of draft.stacks) {
|
|
236
|
+
lines.push("");
|
|
237
|
+
if (stack.applicability === "not-applicable") {
|
|
238
|
+
lines.push(`## ${stack.stack} (not-applicable)`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
renderApplicableStack(lines, stack);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const readiness = isDraftReadyToPersist(draft);
|
|
245
|
+
if (!readiness.ok) {
|
|
246
|
+
lines.push("");
|
|
247
|
+
lines.push("Readiness blockers:");
|
|
248
|
+
for (const blocker of readiness.blockers) {
|
|
249
|
+
lines.push(` - ${describeBlocker(blocker)}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return lines;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function renderApplicableStack(lines: string[], stack: UltraPlanStack): void {
|
|
257
|
+
lines.push(`## ${stack.stack} (applicable)`);
|
|
258
|
+
lines.push(` executor: ${stack.agentSlots.executor.agentName}`);
|
|
259
|
+
lines.push(` tester: ${stack.agentSlots.tester.agentName}`);
|
|
260
|
+
if (stack.agentSlots.domainReviewer) {
|
|
261
|
+
lines.push(` domain reviewer: ${stack.agentSlots.domainReviewer.agentName}`);
|
|
262
|
+
}
|
|
263
|
+
if (stack.agentSlots.stackReviewer) {
|
|
264
|
+
lines.push(` stack reviewer: ${stack.agentSlots.stackReviewer.agentName}`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
for (const domain of stack.domains) {
|
|
268
|
+
lines.push("");
|
|
269
|
+
lines.push(` Domain: ${domain.id} — ${domain.name}`);
|
|
270
|
+
for (const level of ["unit", "integration", "e2e"] as const) {
|
|
271
|
+
const scenarios = domain[level];
|
|
272
|
+
if (scenarios.length === 0) {
|
|
273
|
+
lines.push(` ${level}: —`);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
lines.push(` ${level}:`);
|
|
277
|
+
for (const scenario of scenarios) {
|
|
278
|
+
lines.push(` - ${scenario.id}: ${scenario.title}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function describeBlocker(blocker: { code: string; stack?: string; domainId?: string; slot?: string }): string {
|
|
285
|
+
switch (blocker.code) {
|
|
286
|
+
case "empty-session":
|
|
287
|
+
return "No applicable stacks (edit applicability)";
|
|
288
|
+
case "empty-applicable-stack":
|
|
289
|
+
return `${blocker.stack} has no domains (edit ${blocker.stack}.domains)`;
|
|
290
|
+
case "empty-domain":
|
|
291
|
+
return `${blocker.stack}.${blocker.domainId} has no scenarios (edit ${blocker.stack}.${blocker.domainId}.scenarios)`;
|
|
292
|
+
case "missing-required-slot":
|
|
293
|
+
return `${blocker.stack} is missing required slot ${blocker.slot}`;
|
|
294
|
+
default:
|
|
295
|
+
return blocker.code;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Render the multi-stage authoring pipeline status for a session whose manifest carries an
|
|
301
|
+
* `authoring` block. Mirrors `renderUltraPlanStatus`'s line-oriented format.
|
|
302
|
+
*/
|
|
303
|
+
export function renderUltraPlanAuthoringStatus(
|
|
304
|
+
sessionId: string,
|
|
305
|
+
state: UltraPlanAuthoringState,
|
|
306
|
+
events: UltraPlanAuthoringPipelineEvent[] = [],
|
|
307
|
+
): string {
|
|
308
|
+
const lines: string[] = [
|
|
309
|
+
`Session: ${sessionId}`,
|
|
310
|
+
`Pipeline: ${state.pipeline}`,
|
|
311
|
+
`Stage: ${state.stage}`,
|
|
312
|
+
`Status: ${state.stageStatus}`,
|
|
313
|
+
`Iteration: ${state.iteration}`,
|
|
314
|
+
];
|
|
315
|
+
if (state.stallReentryCount > 0) {
|
|
316
|
+
lines.push(`Stall re-entries: ${state.stallReentryCount}`);
|
|
317
|
+
}
|
|
318
|
+
const artifactKeys = Object.entries(state.artifacts)
|
|
319
|
+
.filter(([, v]) => v !== undefined && v !== null && (Array.isArray(v) ? v.length > 0 : true))
|
|
320
|
+
.map(([k]) => k);
|
|
321
|
+
lines.push(`Artifacts: ${artifactKeys.length === 0 ? "\u2014" : artifactKeys.join(", ")}`);
|
|
322
|
+
lines.push(`Started: ${state.startedAt}`);
|
|
323
|
+
lines.push(`Updated: ${state.updatedAt}`);
|
|
324
|
+
if (state.blocker) {
|
|
325
|
+
lines.push(`Blocker: ${state.blocker.code} \u2014 ${state.blocker.message}`);
|
|
326
|
+
lines.push(`Recovery: ${state.blocker.recoveryMode}`);
|
|
327
|
+
}
|
|
328
|
+
lines.push(`Next action: ${describeNextAuthoringAction(state)}`);
|
|
329
|
+
if (events.length > 0) {
|
|
330
|
+
lines.push("");
|
|
331
|
+
lines.push("Recent pipeline events:");
|
|
332
|
+
for (const ev of events.slice(-5)) {
|
|
333
|
+
lines.push(` ${ev.recordedAt} [${ev.stage}/${ev.stageStatus}] ${ev.summary || ""}`.trimEnd());
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return lines.join("\n");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function describeNextAuthoringAction(state: UltraPlanAuthoringState): string {
|
|
340
|
+
if (state.blocker) return `Resolve blocker ${state.blocker.code}`;
|
|
341
|
+
if (state.stageStatus === "awaiting-user") return `Confirm ${state.stage} to advance`;
|
|
342
|
+
if (state.stageStatus === "running") return `Resume ${state.stage}`;
|
|
343
|
+
if (state.stageStatus === "blocked") return `Repair ${state.stage} blocker`;
|
|
344
|
+
const next = nextStageOf(state.stage);
|
|
345
|
+
if (!next) return "Approval pending";
|
|
346
|
+
return `Run ${next}`;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function nextStageOf(stage: UltraPlanAuthoringStage): UltraPlanAuthoringStage | null {
|
|
350
|
+
switch (stage) {
|
|
351
|
+
case "intake": return "scout";
|
|
352
|
+
case "scout": return "discover";
|
|
353
|
+
case "discover": return "research";
|
|
354
|
+
case "research": return "synthesize";
|
|
355
|
+
case "synthesize": return "review";
|
|
356
|
+
case "review": return "approve";
|
|
357
|
+
case "approve": return null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import type { PlatformPaths } from "../platform/types.js";
|
|
3
|
+
import type { UltraPlanStackId } from "../types.js";
|
|
4
|
+
import { resolveRepoIdentityRootFromFs, resolveRepoRootFromFs } from "../workspace/repo-root.js";
|
|
5
|
+
import { projectSlugFromRepoRoot } from "../workspace/project-slug.js";
|
|
6
|
+
|
|
7
|
+
// Canonical directory name for the UltraPlan namespace under the global state root. Kept here so
|
|
8
|
+
// no other UltraPlan module needs to know this token.
|
|
9
|
+
const ULTRAPLANS_DIR = "ultraplans";
|
|
10
|
+
|
|
11
|
+
// Canonical artifact filenames. Exported so UltraPlan command/presenter code that builds manifest
|
|
12
|
+
// references does not need to inline the strings (centralization-scan guardrail from the delta
|
|
13
|
+
// spec §1).
|
|
14
|
+
export const ULTRAPLAN_AUTHORED_JSON_FILENAME = "authored.json";
|
|
15
|
+
export const ULTRAPLAN_AUTHORED_MARKDOWN_FILENAME = "authored.md";
|
|
16
|
+
export const ULTRAPLAN_MANIFEST_FILENAME = "manifest.json";
|
|
17
|
+
export const ULTRAPLAN_INDEX_FILENAME = "index.json";
|
|
18
|
+
export const ULTRAPLAN_EXECUTION_LOG_FILENAME = "execution-log.jsonl";
|
|
19
|
+
export const ULTRAPLAN_HOOKS_LOG_FILENAME = "hooks-log.jsonl";
|
|
20
|
+
export const ULTRAPLAN_RUNTIME_TRACKER_FILENAME = "runtime-tracker.json";
|
|
21
|
+
export const ULTRAPLAN_MIGRATION_RECORD_FILENAME = "migration.json";
|
|
22
|
+
const ULTRAPLAN_BATCH_RUNS_DIRNAME = "batch-runs";
|
|
23
|
+
export const ULTRAPLAN_BATCH_RUN_FILENAME = "run.json";
|
|
24
|
+
export const ULTRAPLAN_BATCH_JOURNAL_FILENAME = "journal.jsonl";
|
|
25
|
+
export const ULTRAPLAN_ACTIVE_BATCH_RUN_FILENAME = "active-run.json";
|
|
26
|
+
|
|
27
|
+
// Authoring pipeline filenames (multi-stage GSD-style flow). All live under <session>/authoring/.
|
|
28
|
+
const ULTRAPLAN_AUTHORING_DIRNAME = "authoring";
|
|
29
|
+
export const ULTRAPLAN_AUTHORING_INTAKE_FILENAME = "intake.json";
|
|
30
|
+
export const ULTRAPLAN_AUTHORING_SCOUT_FILENAME = "scout.json";
|
|
31
|
+
export const ULTRAPLAN_AUTHORING_DISCUSS_FILENAME = "discuss.md";
|
|
32
|
+
export const ULTRAPLAN_AUTHORING_DECISIONS_FILENAME = "decisions.jsonl";
|
|
33
|
+
export const ULTRAPLAN_AUTHORING_DEFERRED_IDEAS_FILENAME = "deferred-ideas.md";
|
|
34
|
+
const ULTRAPLAN_AUTHORING_RESEARCH_DIRNAME = "research";
|
|
35
|
+
export const ULTRAPLAN_AUTHORING_RESEARCH_SUMMARY_FILENAME = "SUMMARY.md";
|
|
36
|
+
const ULTRAPLAN_AUTHORING_DRAFTS_DIRNAME = "drafts";
|
|
37
|
+
export const ULTRAPLAN_AUTHORING_DRAFT_AUTHORED_JSON_FILENAME = "authored.json";
|
|
38
|
+
export const ULTRAPLAN_AUTHORING_DRAFT_AUTHORED_MD_FILENAME = "authored.md";
|
|
39
|
+
export const ULTRAPLAN_AUTHORING_DRAFT_PLANNER_JSON_FILENAME = "authored.planner.json";
|
|
40
|
+
export const ULTRAPLAN_AUTHORING_DRAFT_MANIFEST_FILENAME = "manifest.json";
|
|
41
|
+
export const ULTRAPLAN_AUTHORING_DRAFT_FINDINGS_FILENAME = "findings.json";
|
|
42
|
+
export const ULTRAPLAN_AUTHORING_PIPELINE_LOG_FILENAME = "pipeline-log.jsonl";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the active checkout root for the given cwd. Legacy repo-local helpers still target the
|
|
46
|
+
* active checkout, not the canonical UltraPlan identity root.
|
|
47
|
+
*/
|
|
48
|
+
function resolveCheckoutRoot(cwd: string): string {
|
|
49
|
+
return path.resolve(resolveRepoRootFromFs(cwd));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the canonical project identity root for the given cwd. Linked worktrees of one repo
|
|
54
|
+
* must converge on the same identity root so they share one UltraPlan storage location.
|
|
55
|
+
*/
|
|
56
|
+
function resolveProjectIdentityRoot(cwd: string): string {
|
|
57
|
+
return path.resolve(resolveRepoIdentityRootFromFs(cwd));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getUltraplanProjectName(cwd: string): string {
|
|
61
|
+
const projectName = path.basename(path.normalize(resolveProjectIdentityRoot(cwd)));
|
|
62
|
+
if (!projectName) {
|
|
63
|
+
throw new Error(`Unable to derive ultraplan project name from cwd: ${cwd}`);
|
|
64
|
+
}
|
|
65
|
+
return projectName;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Canonical UltraPlan root: `${home}/.omp/supipowers/projects/<projectSlug>/ultraplans`.
|
|
70
|
+
* Every other UltraPlan path helper composes on top of this single function.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveUltraPlanRoot(paths: PlatformPaths, cwd: string): string {
|
|
73
|
+
const repoIdentityRoot = resolveProjectIdentityRoot(cwd);
|
|
74
|
+
const slug = projectSlugFromRepoRoot(repoIdentityRoot);
|
|
75
|
+
return paths.global("projects", slug, ULTRAPLANS_DIR);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Project-scoped directory under the global state root (parent of `ultraplans/`). */
|
|
79
|
+
export function getUltraplanProjectDir(paths: PlatformPaths, cwd: string): string {
|
|
80
|
+
const repoIdentityRoot = resolveProjectIdentityRoot(cwd);
|
|
81
|
+
const slug = projectSlugFromRepoRoot(repoIdentityRoot);
|
|
82
|
+
return paths.global("projects", slug);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function getUltraplansDir(paths: PlatformPaths, cwd: string): string {
|
|
86
|
+
return resolveUltraPlanRoot(paths, cwd);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function getUltraplanIndexPath(paths: PlatformPaths, cwd: string): string {
|
|
90
|
+
return path.join(resolveUltraPlanRoot(paths, cwd), ULTRAPLAN_INDEX_FILENAME);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function getUltraplanBatchRunsDir(paths: PlatformPaths, cwd: string): string {
|
|
94
|
+
return path.join(resolveUltraPlanRoot(paths, cwd), ULTRAPLAN_BATCH_RUNS_DIRNAME);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function getUltraplanActiveBatchRunPath(paths: PlatformPaths, cwd: string): string {
|
|
98
|
+
return path.join(getUltraplanBatchRunsDir(paths, cwd), ULTRAPLAN_ACTIVE_BATCH_RUN_FILENAME);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function getUltraplanBatchRunDir(paths: PlatformPaths, cwd: string, runId: string): string {
|
|
102
|
+
return path.join(getUltraplanBatchRunsDir(paths, cwd), runId);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getUltraplanBatchRunPath(paths: PlatformPaths, cwd: string, runId: string): string {
|
|
106
|
+
return path.join(getUltraplanBatchRunDir(paths, cwd, runId), ULTRAPLAN_BATCH_RUN_FILENAME);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getUltraplanBatchJournalPath(paths: PlatformPaths, cwd: string, runId: string): string {
|
|
110
|
+
return path.join(getUltraplanBatchRunDir(paths, cwd, runId), ULTRAPLAN_BATCH_JOURNAL_FILENAME);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function getUltraplanSessionDir(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
114
|
+
return path.join(resolveUltraPlanRoot(paths, cwd), sessionId);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getUltraplanManifestPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
118
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_MANIFEST_FILENAME);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function getUltraplanAuthoredJsonPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
122
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORED_JSON_FILENAME);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function getUltraplanAuthoredMarkdownPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
126
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORED_MARKDOWN_FILENAME);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function getUltraplanExecutionLogPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
130
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_EXECUTION_LOG_FILENAME);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function getUltraplanHooksLogPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
134
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_HOOKS_LOG_FILENAME);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function getUltraplanRuntimeTrackerPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
138
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_RUNTIME_TRACKER_FILENAME);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function getUltraplanMigrationRecordPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
142
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_MIGRATION_RECORD_FILENAME);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function getUltraplanReviewDir(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
146
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), "review");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function getUltraplanStackReviewDir(
|
|
150
|
+
paths: PlatformPaths,
|
|
151
|
+
cwd: string,
|
|
152
|
+
sessionId: string,
|
|
153
|
+
stack: UltraPlanStackId,
|
|
154
|
+
): string {
|
|
155
|
+
return path.join(getUltraplanReviewDir(paths, cwd, sessionId), stack);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function getUltraplanDomainReviewPath(
|
|
159
|
+
paths: PlatformPaths,
|
|
160
|
+
cwd: string,
|
|
161
|
+
sessionId: string,
|
|
162
|
+
stack: UltraPlanStackId,
|
|
163
|
+
domainId: string,
|
|
164
|
+
): string {
|
|
165
|
+
return path.join(getUltraplanStackReviewDir(paths, cwd, sessionId, stack), "domains", `${domainId}.json`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function getUltraplanStackReviewPath(
|
|
169
|
+
paths: PlatformPaths,
|
|
170
|
+
cwd: string,
|
|
171
|
+
sessionId: string,
|
|
172
|
+
stack: UltraPlanStackId,
|
|
173
|
+
): string {
|
|
174
|
+
return path.join(getUltraplanStackReviewDir(paths, cwd, sessionId, stack), "stack.json");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// Authoring pipeline path helpers. All paths are anchored under the session dir.
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
export function getUltraplanAuthoringDir(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
183
|
+
return path.join(getUltraplanSessionDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_DIRNAME);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function getUltraplanAuthoringIntakePath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
187
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_INTAKE_FILENAME);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function getUltraplanAuthoringScoutPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
191
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_SCOUT_FILENAME);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function getUltraplanAuthoringDiscussPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
195
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_DISCUSS_FILENAME);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function getUltraplanAuthoringDecisionsPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
199
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_DECISIONS_FILENAME);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function getUltraplanAuthoringDeferredIdeasPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
203
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_DEFERRED_IDEAS_FILENAME);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getUltraplanAuthoringResearchDir(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
207
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_RESEARCH_DIRNAME);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function getUltraplanAuthoringResearchSummaryPath(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
211
|
+
return path.join(
|
|
212
|
+
getUltraplanAuthoringResearchDir(paths, cwd, sessionId),
|
|
213
|
+
ULTRAPLAN_AUTHORING_RESEARCH_SUMMARY_FILENAME,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function getUltraplanAuthoringResearchStackPath(
|
|
218
|
+
paths: PlatformPaths,
|
|
219
|
+
cwd: string,
|
|
220
|
+
sessionId: string,
|
|
221
|
+
stack: UltraPlanStackId,
|
|
222
|
+
): string {
|
|
223
|
+
return path.join(getUltraplanAuthoringResearchDir(paths, cwd, sessionId), `${stack}.md`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function getUltraplanAuthoringDraftsDir(paths: PlatformPaths, cwd: string, sessionId: string): string {
|
|
227
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_DRAFTS_DIRNAME);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function getUltraplanAuthoringDraftIterationDir(
|
|
231
|
+
paths: PlatformPaths,
|
|
232
|
+
cwd: string,
|
|
233
|
+
sessionId: string,
|
|
234
|
+
iteration: number,
|
|
235
|
+
): string {
|
|
236
|
+
if (!Number.isInteger(iteration) || iteration < 1) {
|
|
237
|
+
throw new Error(`Iteration must be a positive integer; got ${iteration}`);
|
|
238
|
+
}
|
|
239
|
+
return path.join(getUltraplanAuthoringDraftsDir(paths, cwd, sessionId), `iteration-${iteration}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function getUltraplanAuthoringDraftAuthoredJsonPath(
|
|
243
|
+
paths: PlatformPaths,
|
|
244
|
+
cwd: string,
|
|
245
|
+
sessionId: string,
|
|
246
|
+
iteration: number,
|
|
247
|
+
): string {
|
|
248
|
+
return path.join(
|
|
249
|
+
getUltraplanAuthoringDraftIterationDir(paths, cwd, sessionId, iteration),
|
|
250
|
+
ULTRAPLAN_AUTHORING_DRAFT_AUTHORED_JSON_FILENAME,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function getUltraplanAuthoringDraftAuthoredMarkdownPath(
|
|
255
|
+
paths: PlatformPaths,
|
|
256
|
+
cwd: string,
|
|
257
|
+
sessionId: string,
|
|
258
|
+
iteration: number,
|
|
259
|
+
): string {
|
|
260
|
+
return path.join(
|
|
261
|
+
getUltraplanAuthoringDraftIterationDir(paths, cwd, sessionId, iteration),
|
|
262
|
+
ULTRAPLAN_AUTHORING_DRAFT_AUTHORED_MD_FILENAME,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function getUltraplanAuthoringDraftPlannerJsonPath(
|
|
267
|
+
paths: PlatformPaths,
|
|
268
|
+
cwd: string,
|
|
269
|
+
sessionId: string,
|
|
270
|
+
iteration: number,
|
|
271
|
+
): string {
|
|
272
|
+
return path.join(
|
|
273
|
+
getUltraplanAuthoringDraftIterationDir(paths, cwd, sessionId, iteration),
|
|
274
|
+
ULTRAPLAN_AUTHORING_DRAFT_PLANNER_JSON_FILENAME,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function getUltraplanAuthoringDraftManifestPath(
|
|
279
|
+
paths: PlatformPaths,
|
|
280
|
+
cwd: string,
|
|
281
|
+
sessionId: string,
|
|
282
|
+
iteration: number,
|
|
283
|
+
): string {
|
|
284
|
+
return path.join(
|
|
285
|
+
getUltraplanAuthoringDraftIterationDir(paths, cwd, sessionId, iteration),
|
|
286
|
+
ULTRAPLAN_AUTHORING_DRAFT_MANIFEST_FILENAME,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function getUltraplanAuthoringDraftFindingsPath(
|
|
291
|
+
paths: PlatformPaths,
|
|
292
|
+
cwd: string,
|
|
293
|
+
sessionId: string,
|
|
294
|
+
iteration: number,
|
|
295
|
+
): string {
|
|
296
|
+
return path.join(
|
|
297
|
+
getUltraplanAuthoringDraftIterationDir(paths, cwd, sessionId, iteration),
|
|
298
|
+
ULTRAPLAN_AUTHORING_DRAFT_FINDINGS_FILENAME,
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function getUltraplanAuthoringPipelineLogPath(
|
|
303
|
+
paths: PlatformPaths,
|
|
304
|
+
cwd: string,
|
|
305
|
+
sessionId: string,
|
|
306
|
+
): string {
|
|
307
|
+
return path.join(getUltraplanAuthoringDir(paths, cwd, sessionId), ULTRAPLAN_AUTHORING_PIPELINE_LOG_FILENAME);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Returns the relative artifact path for a draft's authored.json under the authoring directory,
|
|
312
|
+
* used in `StageRunResult.artifactPaths` and log entries. Centralised here so stage files
|
|
313
|
+
* never need to embed the forbidden `authored.json` filename literal.
|
|
314
|
+
*/
|
|
315
|
+
export function getUltraplanAuthoringDraftAuthoredRelativePath(iteration: number): string {
|
|
316
|
+
return [
|
|
317
|
+
ULTRAPLAN_AUTHORING_DIRNAME,
|
|
318
|
+
ULTRAPLAN_AUTHORING_DRAFTS_DIRNAME,
|
|
319
|
+
`iteration-${iteration}`,
|
|
320
|
+
ULTRAPLAN_AUTHORING_DRAFT_AUTHORED_JSON_FILENAME,
|
|
321
|
+
].join("/");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
// Legacy (pre-Slice-2) repo-local path helpers. Only the migration engine uses these; after
|
|
326
|
+
// migration runs, the legacy directory is renamed and never written to again.
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
const LEGACY_DOT_DIR = ".omp";
|
|
330
|
+
const LEGACY_PACKAGE_DIR = "supipowers";
|
|
331
|
+
|
|
332
|
+
export function getLegacyUltraplansDir(cwd: string): string {
|
|
333
|
+
return path.join(resolveCheckoutRoot(cwd), LEGACY_DOT_DIR, LEGACY_PACKAGE_DIR, ULTRAPLANS_DIR);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export function getLegacyUltraplanSessionDir(cwd: string, sessionId: string): string {
|
|
337
|
+
return path.join(getLegacyUltraplansDir(cwd), sessionId);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function getLegacyUltraplanIndexPath(cwd: string): string {
|
|
341
|
+
return path.join(getLegacyUltraplansDir(cwd), ULTRAPLAN_INDEX_FILENAME);
|
|
342
|
+
}
|