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
|
@@ -1,31 +1,72 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
1
3
|
import type { Platform, PlatformContext } from "../platform/types.js";
|
|
4
|
+
import { systemPromptText } from "../platform/system-prompt.js";
|
|
2
5
|
import {
|
|
3
6
|
parseSystemPrompt,
|
|
4
7
|
parseIndividualSkills,
|
|
5
8
|
} from "../context/analyzer.js";
|
|
9
|
+
import type { ParsedSkill, PromptSection } from "../context/analyzer.js";
|
|
6
10
|
import {
|
|
7
11
|
detectTechStack,
|
|
8
12
|
buildContextReport,
|
|
9
13
|
} from "../context/optimizer.js";
|
|
10
14
|
import type { ContextReport } from "../context/optimizer.js";
|
|
15
|
+
import {
|
|
16
|
+
buildOptimizationPlan,
|
|
17
|
+
} from "../context/startup-optimizer.js";
|
|
18
|
+
import type {
|
|
19
|
+
ManualOptimizationAction,
|
|
20
|
+
OptimizationPlan,
|
|
21
|
+
WriteRuleAction,
|
|
22
|
+
} from "../context/startup-optimizer.js";
|
|
23
|
+
import { parseManagedRule, renderManagedRule } from "../context/rule-renderer.js";
|
|
24
|
+
import { DEFAULT_TOKENIGNORE_ENTRIES, mergeManagedTokenignore } from "../context/tokenignore.js";
|
|
25
|
+
import {
|
|
26
|
+
parseStartupOptimizerManifest,
|
|
27
|
+
runStartupCheck,
|
|
28
|
+
} from "../context/startup-check.js";
|
|
29
|
+
import type { StartupCheckReport, StartupOptimizerManifest } from "../context/startup-check.js";
|
|
30
|
+
import { getMetricsStore, getSessionId } from "../context-mode/hooks.js";
|
|
11
31
|
|
|
12
32
|
function formatTokens(n: number): string {
|
|
13
33
|
return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);
|
|
14
34
|
}
|
|
15
35
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
36
|
+
interface OptimizeContextArgs {
|
|
37
|
+
apply: boolean;
|
|
38
|
+
check: boolean;
|
|
39
|
+
dryRun: boolean;
|
|
40
|
+
}
|
|
19
41
|
|
|
20
|
-
|
|
21
|
-
|
|
42
|
+
function parseOptimizeContextArgs(args: string | undefined): OptimizeContextArgs {
|
|
43
|
+
const tokens = (args ?? "").trim().split(/\s+/).filter(Boolean);
|
|
44
|
+
return {
|
|
45
|
+
apply: tokens.includes("--apply"),
|
|
46
|
+
check: tokens.includes("--check"),
|
|
47
|
+
dryRun: tokens.includes("--dry-run"),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
22
50
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Handle the `/supi:optimize-context` command. Returns a Promise so that callers
|
|
53
|
+
* (and tests) can await the full flow; the registered command handler does not
|
|
54
|
+
* need to await — exceptions are caught and surfaced via `ctx.ui.notify`.
|
|
55
|
+
*/
|
|
56
|
+
export async function handleOptimizeContext(
|
|
57
|
+
platform: Platform,
|
|
58
|
+
ctx: PlatformContext,
|
|
59
|
+
args?: string,
|
|
60
|
+
): Promise<void> {
|
|
61
|
+
if (!ctx.hasUI) return;
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const parsedArgs = parseOptimizeContextArgs(args);
|
|
65
|
+
const systemPrompt = readSystemPrompt(ctx);
|
|
66
|
+
|
|
67
|
+
if (parsedArgs.check) {
|
|
68
|
+
await runCheck(platform, ctx, systemPrompt);
|
|
69
|
+
return;
|
|
29
70
|
}
|
|
30
71
|
|
|
31
72
|
if (!systemPrompt) {
|
|
@@ -33,35 +74,367 @@ export function handleOptimizeContext(platform: Platform, ctx: PlatformContext):
|
|
|
33
74
|
return;
|
|
34
75
|
}
|
|
35
76
|
|
|
36
|
-
|
|
77
|
+
const techStack = await detectTechStack(platform, ctx.cwd);
|
|
37
78
|
const sections = parseSystemPrompt(systemPrompt);
|
|
38
79
|
const skills = parseIndividualSkills(systemPrompt);
|
|
39
|
-
|
|
40
|
-
// 4. Build raw report
|
|
41
80
|
const report = buildContextReport(sections, skills, techStack);
|
|
81
|
+
const plan = buildOptimizationPlan({
|
|
82
|
+
prompt: systemPrompt,
|
|
83
|
+
sections,
|
|
84
|
+
skills,
|
|
85
|
+
techStack,
|
|
86
|
+
});
|
|
42
87
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
88
|
+
if (parsedArgs.dryRun) {
|
|
89
|
+
await showDryRun(ctx, plan);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (parsedArgs.apply) {
|
|
94
|
+
await applyOptimizationPlan(platform, ctx, plan);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await showReport(platform, ctx, report, plan);
|
|
99
|
+
} catch (err) {
|
|
46
100
|
ctx.ui.notify(`Optimize error: ${(err as Error).message}`, "error");
|
|
47
|
-
}
|
|
101
|
+
}
|
|
48
102
|
}
|
|
49
103
|
|
|
50
104
|
export function registerOptimizeContextCommand(platform: Platform): void {
|
|
51
105
|
platform.registerCommand("supi:optimize-context", {
|
|
52
106
|
description: "Analyze context usage and suggest token optimizations",
|
|
53
|
-
async handler(
|
|
54
|
-
handleOptimizeContext(platform, ctx);
|
|
107
|
+
async handler(args: string | undefined, ctx: any) {
|
|
108
|
+
await handleOptimizeContext(platform, ctx, args);
|
|
55
109
|
},
|
|
56
110
|
});
|
|
57
111
|
}
|
|
58
112
|
|
|
59
113
|
// ── Internal ──────────────────────────────────────────────
|
|
60
114
|
|
|
115
|
+
function readSystemPrompt(ctx: PlatformContext): string | null {
|
|
116
|
+
try {
|
|
117
|
+
const value = (ctx as any).getSystemPrompt?.();
|
|
118
|
+
const text = systemPromptText(value);
|
|
119
|
+
return text.length > 0 ? text : null;
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function runCheck(
|
|
126
|
+
platform: Platform,
|
|
127
|
+
ctx: PlatformContext,
|
|
128
|
+
currentPrompt: string | null,
|
|
129
|
+
): Promise<void> {
|
|
130
|
+
const manifestPath = platform.paths.project(ctx.cwd, "context-optimizer", "manifest.json");
|
|
131
|
+
const tokenignorePath = platform.paths.project(ctx.cwd, ".tokenignore");
|
|
132
|
+
const manifestText = readOptionalFile(manifestPath);
|
|
133
|
+
// Use the same parser the checker uses so the command cannot accept a manifest
|
|
134
|
+
// shape that the check would later reject.
|
|
135
|
+
const parsedManifest = parseStartupOptimizerManifest(manifestText, manifestPath);
|
|
136
|
+
const manifest = typeof parsedManifest === "string" ? null : parsedManifest;
|
|
137
|
+
|
|
138
|
+
const ruleFiles: Record<string, string | null> = {};
|
|
139
|
+
if (manifest) {
|
|
140
|
+
for (const rule of manifest.rules) {
|
|
141
|
+
ruleFiles[rule.path] = readOptionalFile(path.join(ctx.cwd, rule.path));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const currentSkills: ParsedSkill[] = currentPrompt ? parseIndividualSkills(currentPrompt) : [];
|
|
146
|
+
const currentSections: PromptSection[] = currentPrompt ? parseSystemPrompt(currentPrompt) : [];
|
|
147
|
+
|
|
148
|
+
const report = runStartupCheck({
|
|
149
|
+
manifestPath,
|
|
150
|
+
manifestText,
|
|
151
|
+
ruleFiles,
|
|
152
|
+
tokenignorePath,
|
|
153
|
+
tokenignoreText: readOptionalFile(tokenignorePath),
|
|
154
|
+
currentPrompt,
|
|
155
|
+
currentSkills,
|
|
156
|
+
currentSections,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (report.status === "pass") {
|
|
160
|
+
recordStartupOptimizerMetric(report);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ctx.ui.notify(formatCheckReport(report), report.status === "pass" ? "info" : "error");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function readOptionalFile(filePath: string): string | null {
|
|
167
|
+
try {
|
|
168
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
169
|
+
} catch {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function formatCheckReport(report: StartupCheckReport): string {
|
|
175
|
+
const lines = [`Startup optimization check: ${report.status}`];
|
|
176
|
+
if (report.currentBytes != null) {
|
|
177
|
+
lines.push(`Current prompt: ${report.currentBytes} bytes (~${formatTokens(Math.ceil(report.currentBytes / 4))} tokens estimated)`);
|
|
178
|
+
}
|
|
179
|
+
if (report.targetBytes != null) {
|
|
180
|
+
lines.push(`Target: ${report.targetBytes} bytes (~${formatTokens(Math.ceil(report.targetBytes / 4))} tokens estimated)`);
|
|
181
|
+
}
|
|
182
|
+
if (report.issues.length > 0) {
|
|
183
|
+
lines.push("Issues:");
|
|
184
|
+
for (const issue of report.issues) {
|
|
185
|
+
const location = issue.path ? ` at ${issue.path}` : issue.sourceId ? ` for ${issue.sourceId}` : "";
|
|
186
|
+
lines.push(`- ${issue.reason}${location}: ${issue.remediation}`);
|
|
187
|
+
}
|
|
188
|
+
if (report.issues.some((entry) => RUNTIME_DEPENDENT_REASONS.has(entry.reason))) {
|
|
189
|
+
lines.push(
|
|
190
|
+
"Note: rule discovery happens at OMP process startup. If you just ran --apply, restart OMP before running --check so the runtime actually picks up the managed rules in .omp/rules.",
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const RUNTIME_DEPENDENT_REASONS = new Set([
|
|
198
|
+
"still-loaded-source",
|
|
199
|
+
"prompt-over-target",
|
|
200
|
+
"unresolved-manual-action",
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
function recordStartupOptimizerMetric(report: StartupCheckReport): void {
|
|
204
|
+
const store = getMetricsStore();
|
|
205
|
+
if (!store || report.currentBytes == null || report.beforeBytes == null) return;
|
|
206
|
+
try {
|
|
207
|
+
store.record({
|
|
208
|
+
session_id: getSessionId() || "startup-optimizer-check",
|
|
209
|
+
ts: Date.now(),
|
|
210
|
+
layer: "L6",
|
|
211
|
+
tool: "(system)",
|
|
212
|
+
processor: "startup-optimizer",
|
|
213
|
+
before_bytes: report.beforeBytes,
|
|
214
|
+
after_bytes: report.currentBytes,
|
|
215
|
+
cache_hit: 0,
|
|
216
|
+
unique_source_hash: report.sourceSetHash,
|
|
217
|
+
context_tokens: null,
|
|
218
|
+
context_window: null,
|
|
219
|
+
context_percent: null,
|
|
220
|
+
});
|
|
221
|
+
} catch {
|
|
222
|
+
// Metrics are best-effort; check results must still be surfaced.
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function showDryRun(ctx: PlatformContext, plan: OptimizationPlan): Promise<void> {
|
|
227
|
+
const lines = buildPlanPreview(plan);
|
|
228
|
+
await ctx.ui.select("Context Optimization Dry Run", lines, {
|
|
229
|
+
helpText: "Dry-run: no files will be written · Esc to close",
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function buildPlanPreview(plan: OptimizationPlan): string[] {
|
|
234
|
+
const writeRuleCount = plan.actions.filter((action) => action.kind === "write-rule").length;
|
|
235
|
+
const manualCount = plan.actions.filter((action) => action.kind !== "write-rule").length;
|
|
236
|
+
const lines = [
|
|
237
|
+
`Source set: ${plan.sourceSetHash.slice(0, 12)}`,
|
|
238
|
+
`Current: ~${formatTokens(Math.ceil(plan.beforeBytes / 4))} tokens | Estimated after planned removals: ~${formatTokens(Math.ceil(plan.estimatedAfterBytes / 4))} tokens`,
|
|
239
|
+
`Actions: ${writeRuleCount} write-rule, ${manualCount} manual`,
|
|
240
|
+
"",
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
for (const action of plan.actions) {
|
|
244
|
+
if (action.kind === "write-rule") {
|
|
245
|
+
lines.push(`write-rule ${action.mode}: ${action.targetPath}`);
|
|
246
|
+
} else if (action.kind === "manual-disable") {
|
|
247
|
+
lines.push(`manual-disable ${action.sourceName}: ${action.reason}`);
|
|
248
|
+
} else {
|
|
249
|
+
lines.push(`manual-agents-split ${action.sourceName}: ${action.sourceBytes} bytes`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
lines.push("", "Close");
|
|
254
|
+
return lines;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function applyOptimizationPlan(
|
|
258
|
+
platform: Platform,
|
|
259
|
+
ctx: PlatformContext,
|
|
260
|
+
plan: OptimizationPlan,
|
|
261
|
+
): Promise<void> {
|
|
262
|
+
const manifestPath = platform.paths.project(ctx.cwd, "context-optimizer", "manifest.json");
|
|
263
|
+
const tokenignorePath = platform.paths.project(ctx.cwd, ".tokenignore");
|
|
264
|
+
const manifestPreflight = preflightExistingManifest(manifestPath);
|
|
265
|
+
if (manifestPreflight) {
|
|
266
|
+
ctx.ui.notify(manifestPreflight, "error");
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const writeRules = plan.actions.filter((action): action is WriteRuleAction => action.kind === "write-rule");
|
|
271
|
+
const preflight = preflightRuleWrites(ctx.cwd, writeRules);
|
|
272
|
+
if (preflight.conflicts.length > 0) {
|
|
273
|
+
ctx.ui.notify(`Apply blocked: ${preflight.conflicts.join("; ")}`, "error");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (fs.existsSync(tokenignorePath) && !fs.statSync(tokenignorePath).isFile()) {
|
|
278
|
+
ctx.ui.notify(`Apply blocked: ${tokenignorePath} is not a file.`, "error");
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const summary = buildApplySummary(plan, preflight.updates);
|
|
283
|
+
const accepted = await confirmApply(ctx, summary);
|
|
284
|
+
if (!accepted) {
|
|
285
|
+
ctx.ui.notify("Apply cancelled.", "info");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const manifest = buildManifest(plan);
|
|
290
|
+
const tokenignoreExisting = fs.existsSync(tokenignorePath)
|
|
291
|
+
? fs.readFileSync(tokenignorePath, "utf-8")
|
|
292
|
+
: null;
|
|
293
|
+
const tokenignore = mergeManagedTokenignore(tokenignoreExisting, DEFAULT_TOKENIGNORE_ENTRIES);
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
for (const action of writeRules) {
|
|
297
|
+
const target = absoluteRulePath(ctx.cwd, action.targetPath);
|
|
298
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
299
|
+
fs.writeFileSync(target, renderManagedRule(action));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
fs.mkdirSync(path.dirname(tokenignorePath), { recursive: true });
|
|
303
|
+
fs.writeFileSync(tokenignorePath, tokenignore.content);
|
|
304
|
+
|
|
305
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
306
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
ctx.ui.notify(`Apply failed before manifest completion: ${(error as Error).message}`, "error");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// OMP discovers rules during session construction (sdk.ts `createAgentSession`)
|
|
313
|
+
// and the in-process rebuild callback reuses captured rule arrays. Neither
|
|
314
|
+
// `ctx.reload()` nor `newSession()` re-runs that discovery, so the current
|
|
315
|
+
// process can't see the just-written .omp/rules without a full restart.
|
|
316
|
+
// Be honest about this rather than silently calling reload() and lying.
|
|
317
|
+
ctx.ui.notify(
|
|
318
|
+
"Applied deterministic context migration. Restart OMP so the new managed rules in .omp/rules are picked up by rule discovery, then disable the original sources and run /supi:optimize-context --check to validate runtime savings.",
|
|
319
|
+
"info",
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function preflightExistingManifest(manifestPath: string): string | null {
|
|
324
|
+
if (!fs.existsSync(manifestPath)) return null;
|
|
325
|
+
if (!fs.statSync(manifestPath).isFile()) {
|
|
326
|
+
return `Remove or repair ${manifestPath}: existing manifest path is not a file.`;
|
|
327
|
+
}
|
|
328
|
+
const text = fs.readFileSync(manifestPath, "utf-8");
|
|
329
|
+
const parsed = parseStartupOptimizerManifest(text, manifestPath);
|
|
330
|
+
if (typeof parsed === "string") {
|
|
331
|
+
return `Remove or repair malformed startup optimizer manifest at ${manifestPath} before applying.`;
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function preflightRuleWrites(
|
|
337
|
+
cwd: string,
|
|
338
|
+
actions: WriteRuleAction[],
|
|
339
|
+
): { conflicts: string[]; updates: string[] } {
|
|
340
|
+
const conflicts: string[] = [];
|
|
341
|
+
const updates: string[] = [];
|
|
342
|
+
|
|
343
|
+
for (const action of actions) {
|
|
344
|
+
const target = absoluteRulePath(cwd, action.targetPath);
|
|
345
|
+
if (!fs.existsSync(target)) continue;
|
|
346
|
+
const stat = fs.statSync(target);
|
|
347
|
+
if (!stat.isFile()) {
|
|
348
|
+
conflicts.push(`${action.targetPath} exists and is not a file`);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const parsed = parseManagedRule(fs.readFileSync(target, "utf-8"));
|
|
353
|
+
if (parsed.status === "unmanaged") {
|
|
354
|
+
conflicts.push(`${action.targetPath} is unmanaged`);
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (parsed.status === "malformed") {
|
|
358
|
+
conflicts.push(`${action.targetPath} is malformed: ${parsed.error}`);
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (
|
|
362
|
+
parsed.metadata.sourceHash !== action.sourceHash ||
|
|
363
|
+
parsed.metadata.sourceId !== action.sourceId ||
|
|
364
|
+
parsed.metadata.mode !== action.mode
|
|
365
|
+
) {
|
|
366
|
+
updates.push(action.targetPath);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return { conflicts, updates };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function buildApplySummary(plan: OptimizationPlan, updates: string[]): string {
|
|
374
|
+
const writeRuleCount = plan.actions.filter((action) => action.kind === "write-rule").length;
|
|
375
|
+
const manualCount = plan.actions.filter((action) => action.kind !== "write-rule").length;
|
|
376
|
+
const lines = [
|
|
377
|
+
`Write ${writeRuleCount} managed rule file${writeRuleCount === 1 ? "" : "s"}.`,
|
|
378
|
+
`Merge ${DEFAULT_TOKENIGNORE_ENTRIES.length} managed .tokenignore entries.`,
|
|
379
|
+
`Record ${manualCount} manual follow-up action${manualCount === 1 ? "" : "s"}.`,
|
|
380
|
+
`Estimated savings after planned removals: ~${formatTokens(Math.ceil(plan.estimatedSavedBytes / 4))} tokens.`,
|
|
381
|
+
];
|
|
382
|
+
if (updates.length > 0) {
|
|
383
|
+
lines.push(`Managed update candidate${updates.length === 1 ? "" : "s"}: ${updates.join(", ")}`);
|
|
384
|
+
}
|
|
385
|
+
lines.push("Manifest is written last after managed rule and tokenignore writes succeed.");
|
|
386
|
+
return lines.join("\n");
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function confirmApply(ctx: PlatformContext, summary: string): Promise<boolean> {
|
|
390
|
+
const choice = await ctx.ui.select("Apply deterministic context migration?", ["Apply", "Cancel"], {
|
|
391
|
+
helpText: summary,
|
|
392
|
+
});
|
|
393
|
+
return choice === "Apply";
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function buildManifest(plan: OptimizationPlan): StartupOptimizerManifest {
|
|
397
|
+
const tokenignore = mergeManagedTokenignore(null, DEFAULT_TOKENIGNORE_ENTRIES);
|
|
398
|
+
const rules = plan.actions
|
|
399
|
+
.filter((action): action is WriteRuleAction => action.kind === "write-rule")
|
|
400
|
+
.map((action) => ({
|
|
401
|
+
path: action.targetPath,
|
|
402
|
+
mode: action.mode,
|
|
403
|
+
sourceId: action.sourceId,
|
|
404
|
+
sourceName: action.sourceName,
|
|
405
|
+
sourceHash: action.sourceHash,
|
|
406
|
+
slug: action.slug,
|
|
407
|
+
sourceBytes: action.sourceBytes,
|
|
408
|
+
...(action.condition ? { condition: action.condition } : {}),
|
|
409
|
+
...(action.description ? { description: action.description } : {}),
|
|
410
|
+
}));
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
version: 1,
|
|
414
|
+
targetBytes: plan.targetBytes,
|
|
415
|
+
sourceSetHash: plan.sourceSetHash,
|
|
416
|
+
beforeBytes: plan.beforeBytes,
|
|
417
|
+
estimatedAfterBytes: plan.estimatedAfterBytes,
|
|
418
|
+
estimatedSavedBytes: plan.estimatedSavedBytes,
|
|
419
|
+
rules,
|
|
420
|
+
tokenignore: {
|
|
421
|
+
path: ".omp/supipowers/.tokenignore",
|
|
422
|
+
entries: tokenignore.entries,
|
|
423
|
+
hash: tokenignore.hash,
|
|
424
|
+
},
|
|
425
|
+
manualActions: plan.actions.filter((action): action is ManualOptimizationAction => action.kind !== "write-rule"),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function absoluteRulePath(cwd: string, targetPath: string): string {
|
|
430
|
+
return path.join(cwd, targetPath);
|
|
431
|
+
}
|
|
432
|
+
|
|
61
433
|
async function showReport(
|
|
62
434
|
platform: Platform,
|
|
63
435
|
ctx: PlatformContext,
|
|
64
436
|
report: ContextReport,
|
|
437
|
+
plan: OptimizationPlan,
|
|
65
438
|
): Promise<void> {
|
|
66
439
|
const techList = [
|
|
67
440
|
...report.techStack.languages,
|
|
@@ -76,7 +449,6 @@ async function showReport(
|
|
|
76
449
|
"",
|
|
77
450
|
];
|
|
78
451
|
|
|
79
|
-
// Skills breakdown
|
|
80
452
|
if (report.skills.length === 0) {
|
|
81
453
|
lines.push("No skills detected in system prompt.");
|
|
82
454
|
} else {
|
|
@@ -90,7 +462,6 @@ async function showReport(
|
|
|
90
462
|
}
|
|
91
463
|
}
|
|
92
464
|
|
|
93
|
-
// Non-skill sections
|
|
94
465
|
if (report.sections.length > 0) {
|
|
95
466
|
lines.push("");
|
|
96
467
|
lines.push("Other sections:");
|
|
@@ -105,12 +476,22 @@ async function showReport(
|
|
|
105
476
|
|
|
106
477
|
const message = lines.join("\n");
|
|
107
478
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
:
|
|
479
|
+
const choice = await ctx.ui.select(
|
|
480
|
+
"Context Optimization",
|
|
481
|
+
[message, "▶ Optimize with AI", "Apply deterministic migration", "Run check", "Close"],
|
|
482
|
+
{ helpText: "Select an action · Esc to close" },
|
|
483
|
+
);
|
|
112
484
|
|
|
113
|
-
if (!
|
|
485
|
+
if (!choice || choice === "Close") return;
|
|
486
|
+
if (choice === "Apply deterministic migration") {
|
|
487
|
+
await applyOptimizationPlan(platform, ctx, plan);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (choice === "Run check") {
|
|
491
|
+
await runCheck(platform, ctx, readSystemPrompt(ctx));
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (!choice.includes("Optimize")) return;
|
|
114
495
|
|
|
115
496
|
platform.sendMessage(
|
|
116
497
|
{
|
|
@@ -138,7 +519,6 @@ function buildOptimizationPrompt(report: ContextReport): string {
|
|
|
138
519
|
lines.push(`Project tech stack: **${techList || "unknown"}**`);
|
|
139
520
|
lines.push("");
|
|
140
521
|
|
|
141
|
-
// Skill inventory
|
|
142
522
|
if (report.skills.length > 0) {
|
|
143
523
|
lines.push("## Skills currently loaded");
|
|
144
524
|
lines.push("");
|
|
@@ -151,7 +531,6 @@ function buildOptimizationPrompt(report: ContextReport): string {
|
|
|
151
531
|
lines.push("");
|
|
152
532
|
}
|
|
153
533
|
|
|
154
|
-
// Section inventory
|
|
155
534
|
if (report.sections.length > 0) {
|
|
156
535
|
lines.push("## Other prompt sections");
|
|
157
536
|
lines.push("");
|
package/src/commands/plan.ts
CHANGED
|
@@ -16,6 +16,7 @@ import * as path from "node:path";
|
|
|
16
16
|
import { modelRegistry } from "../config/model-registry-instance.js";
|
|
17
17
|
import { resolveModelForAction, createModelBridge, applyModelOverride } from "../config/model-resolver.js";
|
|
18
18
|
import { loadModelConfig } from "../config/model-config.js";
|
|
19
|
+
import { getProjectStatePath } from "../workspace/state-paths.js";
|
|
19
20
|
import { cancelPlanTracking, startPlanTracking } from "../planning/approval-flow.js";
|
|
20
21
|
import { stopVisualServer } from "../visual/stop-server.js";
|
|
21
22
|
|
|
@@ -158,6 +159,7 @@ export function registerPlanCommand(platform: Platform): void {
|
|
|
158
159
|
topic: planningTopic,
|
|
159
160
|
skillContent: skillContent || undefined,
|
|
160
161
|
dotDirDisplay: platform.paths.dotDirDisplay,
|
|
162
|
+
plansDir: getProjectStatePath(platform.paths, ctx.cwd, "plans"),
|
|
161
163
|
isQuick: quickMode,
|
|
162
164
|
};
|
|
163
165
|
|