supipowers 1.5.3 → 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 +131 -42
- 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 +18 -8
- 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 +221 -109
- package/src/review/fixer.ts +10 -6
- package/src/review/multi-agent-runner.ts +114 -13
- 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 +1 -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 +1399 -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,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultraplan-review-structure
|
|
3
|
+
description: Structural integrity checker — verifies every applicable stack has domains and scenarios, all fields are present, IDs are unique, and the dependency graph is acyclic
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UltraPlan Review: Structure Checker
|
|
7
|
+
|
|
8
|
+
Verify the structural integrity of a synthesized draft. This checker runs as part of the review stage. It does not evaluate correctness of content — it verifies that the shape of the plan satisfies the invariants required for execution.
|
|
9
|
+
|
|
10
|
+
## Quick Reference
|
|
11
|
+
|
|
12
|
+
| Aspect | Detail |
|
|
13
|
+
|--------|--------|
|
|
14
|
+
| **Inputs** | Draft `authored.json`; intake artifact (to know which stacks are applicable) |
|
|
15
|
+
| **Output** | Findings via `ultraplan_review_finding` with `source: "structure-checker"` |
|
|
16
|
+
| **Scope** | Shape, presence, uniqueness, and graph constraints only |
|
|
17
|
+
| **Storage tool** | `ultraplan_review_finding` — one call per distinct structural violation |
|
|
18
|
+
|
|
19
|
+
## Checks
|
|
20
|
+
|
|
21
|
+
### Check 1 — Stack Coverage
|
|
22
|
+
|
|
23
|
+
Every stack marked `applicable` in the intake MUST appear in `authored.stacks` with at least one domain.
|
|
24
|
+
|
|
25
|
+
- BLOCKER if an applicable stack is absent from `authored.stacks`.
|
|
26
|
+
- BLOCKER if an applicable stack is present but has zero domains.
|
|
27
|
+
- WARNING if a stack marked `unknown` in the intake is absent (the planner may have determined it is not needed, but should confirm).
|
|
28
|
+
|
|
29
|
+
### Check 2 — Domain Coverage
|
|
30
|
+
|
|
31
|
+
Every domain in every stack MUST have at least one scenario.
|
|
32
|
+
|
|
33
|
+
- BLOCKER if a domain has zero scenarios.
|
|
34
|
+
|
|
35
|
+
### Check 3 — Required Scenario Fields
|
|
36
|
+
|
|
37
|
+
Every scenario MUST have all of: `id`, `title`, `level`, `slot`, `steps`, `dependencies`.
|
|
38
|
+
|
|
39
|
+
- BLOCKER if any field is missing or null on any scenario.
|
|
40
|
+
- BLOCKER if `steps` is an empty array.
|
|
41
|
+
- BLOCKER if `level` is not one of `unit`, `integration`, `e2e`.
|
|
42
|
+
- BLOCKER if `dependencies` is absent (empty array `[]` is valid).
|
|
43
|
+
|
|
44
|
+
### Check 4 — ID Uniqueness
|
|
45
|
+
|
|
46
|
+
All scenario IDs across all stacks and domains MUST be globally unique.
|
|
47
|
+
|
|
48
|
+
- BLOCKER if any two scenarios share the same `id`.
|
|
49
|
+
|
|
50
|
+
### Check 5 — Dependency Graph Validity
|
|
51
|
+
|
|
52
|
+
For every scenario that lists dependencies:
|
|
53
|
+
- Each dependency ID MUST resolve to an existing scenario.
|
|
54
|
+
- The graph MUST be acyclic.
|
|
55
|
+
|
|
56
|
+
Detection algorithm: perform a depth-first traversal from each scenario. If you encounter a node already on the current path, a cycle exists.
|
|
57
|
+
|
|
58
|
+
- BLOCKER if a dependency ID does not resolve to an existing scenario.
|
|
59
|
+
- BLOCKER if a cycle is detected. Report all scenario IDs in the cycle in the `message`.
|
|
60
|
+
|
|
61
|
+
### Check 6 — Slot Presence
|
|
62
|
+
|
|
63
|
+
Every `slot` value on every scenario MUST be a non-empty string.
|
|
64
|
+
|
|
65
|
+
- BLOCKER if `slot` is empty, null, or whitespace.
|
|
66
|
+
|
|
67
|
+
## Finding Format
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
ultraplan_review_finding({
|
|
71
|
+
id: "struct-<N>",
|
|
72
|
+
severity: "BLOCKER" | "WARNING",
|
|
73
|
+
source: "structure-checker",
|
|
74
|
+
target: {
|
|
75
|
+
stack: "<stack-id>" | null,
|
|
76
|
+
domainId: "<domain-id>" | null,
|
|
77
|
+
scenarioId: "<scenario-id>" | null
|
|
78
|
+
},
|
|
79
|
+
message: string, // what is structurally wrong and where
|
|
80
|
+
recommendation: string // what to add, fix, or remove
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Set `target` fields to the most specific level at which the violation occurs. If a stack is missing entirely, `domainId` and `scenarioId` are null.
|
|
85
|
+
|
|
86
|
+
## Process
|
|
87
|
+
|
|
88
|
+
Run all six checks in order. Do not stop at the first BLOCKER — complete all checks and emit all findings.
|
|
89
|
+
|
|
90
|
+
### Example Finding — Missing Required Field
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
ultraplan_review_finding({
|
|
94
|
+
id: "struct-1",
|
|
95
|
+
severity: "BLOCKER",
|
|
96
|
+
source: "structure-checker",
|
|
97
|
+
target: { stack: "backend", domainId: "auth", scenarioId: "auth-login-happy" },
|
|
98
|
+
message: "Scenario 'auth-login-happy' in backend/auth is missing the 'slot' field.",
|
|
99
|
+
recommendation: "Add a slot value matching the TDD ownership rules, e.g. 'backend-executor' for unit-level scenarios."
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## MUST DO / MUST NOT DO
|
|
104
|
+
|
|
105
|
+
| MUST DO | MUST NOT DO |
|
|
106
|
+
|---------|-------------|
|
|
107
|
+
| Check all six structural invariants | Stop checking after the first BLOCKER |
|
|
108
|
+
| Report every violation as a separate finding | Batch multiple violations into one finding |
|
|
109
|
+
| Detect and report all cycle participants | Report only one node in a cycle |
|
|
110
|
+
| Set `target` to the most specific location | Use null targets when a specific location is available |
|
|
111
|
+
| Complete all checks even if count of findings is high | Skip checks to reduce finding volume |
|
|
112
|
+
|
|
113
|
+
## Final Checklist
|
|
114
|
+
|
|
115
|
+
- [ ] All six checks executed
|
|
116
|
+
- [ ] Every applicable stack verified for domain coverage
|
|
117
|
+
- [ ] ID uniqueness verified across all stacks globally
|
|
118
|
+
- [ ] Dependency graph traversed for cycles
|
|
119
|
+
- [ ] Every finding has a specific `target` and actionable `recommendation`
|
|
120
|
+
- [ ] Zero findings explicitly recorded if no violations found (emit no calls, do not suppress output)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultraplan-review-tdd
|
|
3
|
+
description: TDD ownership correctness checker — verifies executor/tester slot assignments match scenario levels and every scenario's first step is a failing test
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UltraPlan Review: TDD Checker
|
|
7
|
+
|
|
8
|
+
Verify that every scenario is assigned to the correct slot for its test level and that every scenario's step sequence begins with a failing test. This checker runs as part of the review stage.
|
|
9
|
+
|
|
10
|
+
## Quick Reference
|
|
11
|
+
|
|
12
|
+
| Aspect | Detail |
|
|
13
|
+
|--------|--------|
|
|
14
|
+
| **Inputs** | Draft `authored.json` |
|
|
15
|
+
| **Output** | Findings via `ultraplan_review_finding` with `source: "tdd-checker"` |
|
|
16
|
+
| **Scope** | Slot-to-level alignment, red-test step presence, proof obligations |
|
|
17
|
+
| **Storage tool** | `ultraplan_review_finding` — one call per distinct TDD violation |
|
|
18
|
+
|
|
19
|
+
## TDD Ownership Rules
|
|
20
|
+
|
|
21
|
+
| Level | Valid slots | Invalid slots |
|
|
22
|
+
|-------|-------------|---------------|
|
|
23
|
+
| `unit` | `frontend-executor`, `backend-executor`, `infrastructure-executor` | Any tester or domain-reviewer slot |
|
|
24
|
+
| `integration` | `frontend-tester`, `backend-tester`, `infrastructure-tester` | Any executor or domain-reviewer slot |
|
|
25
|
+
| `e2e` | `frontend-tester`, `backend-tester`, `infrastructure-tester`, `frontend-domain-reviewer`, `backend-domain-reviewer`, `infrastructure-domain-reviewer` | Any executor slot |
|
|
26
|
+
|
|
27
|
+
A slot name is invalid for a level if it does not appear in the "Valid slots" column.
|
|
28
|
+
|
|
29
|
+
## Checks
|
|
30
|
+
|
|
31
|
+
### Check 1 — Slot-Level Alignment
|
|
32
|
+
|
|
33
|
+
Every scenario's `slot` MUST be in the valid-slots list for its `level`.
|
|
34
|
+
|
|
35
|
+
Severity:
|
|
36
|
+
- BLOCKER if a `unit` scenario uses a tester or domain-reviewer slot.
|
|
37
|
+
- BLOCKER if an `integration` scenario uses an executor or domain-reviewer slot.
|
|
38
|
+
- BLOCKER if an `e2e` scenario uses an executor slot.
|
|
39
|
+
|
|
40
|
+
### Check 2 — Slot-Stack Consistency
|
|
41
|
+
|
|
42
|
+
The slot's stack prefix MUST match the scenario's containing stack.
|
|
43
|
+
|
|
44
|
+
- BLOCKER if a scenario in `frontend` stack uses a `backend-*` or `infrastructure-*` slot.
|
|
45
|
+
- BLOCKER if a scenario in `backend` stack uses a `frontend-*` or `infrastructure-*` slot.
|
|
46
|
+
- BLOCKER if a scenario in `infrastructure` stack uses a `frontend-*` or `backend-*` slot.
|
|
47
|
+
|
|
48
|
+
### Check 3 — Red-Test Step Presence
|
|
49
|
+
|
|
50
|
+
Every scenario's `steps` array MUST contain a step that creates and runs a failing test before any implementation step.
|
|
51
|
+
|
|
52
|
+
Detection: The first step MUST contain language indicating test creation and failure verification. Acceptable signals: "write a failing test", "add a failing test", "run the test and confirm it fails", "commit the red test". Presence of implementation language in the first step without a preceding test step is a violation.
|
|
53
|
+
|
|
54
|
+
Severity:
|
|
55
|
+
- BLOCKER if the first step does not write or run a test.
|
|
56
|
+
- BLOCKER if no step in the array runs the test before implementation steps begin.
|
|
57
|
+
- WARNING if a step writes a test but does not verify it fails (does not mention "fails", "red", or "failing").
|
|
58
|
+
|
|
59
|
+
### Check 4 — Proof Obligation Completeness
|
|
60
|
+
|
|
61
|
+
For `unit` scenarios: the steps MUST include a step that runs the test after implementation and confirms it passes.
|
|
62
|
+
|
|
63
|
+
For `integration` and `e2e` scenarios: the steps MUST include a step that runs the full test suite for the relevant layer after implementation.
|
|
64
|
+
|
|
65
|
+
Severity:
|
|
66
|
+
- WARNING if no "verify it passes" step exists after implementation.
|
|
67
|
+
|
|
68
|
+
### Check 5 — No Implementation Before Red Test
|
|
69
|
+
|
|
70
|
+
No implementation step (writing source code, calling an API, creating a database migration) MUST appear before the first red-test step.
|
|
71
|
+
|
|
72
|
+
Severity:
|
|
73
|
+
- BLOCKER if an implementation step precedes the red-test step.
|
|
74
|
+
|
|
75
|
+
## Finding Format
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
ultraplan_review_finding({
|
|
79
|
+
id: "tdd-<N>",
|
|
80
|
+
severity: "BLOCKER" | "WARNING",
|
|
81
|
+
source: "tdd-checker",
|
|
82
|
+
target: {
|
|
83
|
+
stack: "<stack-id>",
|
|
84
|
+
domainId: "<domain-id>",
|
|
85
|
+
scenarioId: "<scenario-id>"
|
|
86
|
+
},
|
|
87
|
+
message: string,
|
|
88
|
+
recommendation: string
|
|
89
|
+
})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Every TDD finding MUST include all three target fields — the violation is always locatable to a specific scenario.
|
|
93
|
+
|
|
94
|
+
## Process
|
|
95
|
+
|
|
96
|
+
Run all five checks across every scenario. Do not stop at the first BLOCKER.
|
|
97
|
+
|
|
98
|
+
### Example Finding — Wrong Slot for Level
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
ultraplan_review_finding({
|
|
102
|
+
id: "tdd-1",
|
|
103
|
+
severity: "BLOCKER",
|
|
104
|
+
source: "tdd-checker",
|
|
105
|
+
target: { stack: "backend", domainId: "auth", scenarioId: "auth-login-unit" },
|
|
106
|
+
message: "Scenario 'auth-login-unit' has level 'unit' but is assigned slot 'backend-tester'. Unit scenarios must use executor slots.",
|
|
107
|
+
recommendation: "Change slot to 'backend-executor'."
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Example Finding — Missing Red-Test Step
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
ultraplan_review_finding({
|
|
115
|
+
id: "tdd-2",
|
|
116
|
+
severity: "BLOCKER",
|
|
117
|
+
source: "tdd-checker",
|
|
118
|
+
target: { stack: "frontend", domainId: "dashboard", scenarioId: "dashboard-load" },
|
|
119
|
+
message: "Scenario 'dashboard-load' first step is 'Implement the data fetching hook', which is an implementation step. No preceding failing test step exists.",
|
|
120
|
+
recommendation: "Prepend a step: 'Write a failing test for the dashboard data fetching hook and run it to confirm it fails.'"
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## MUST DO / MUST NOT DO
|
|
125
|
+
|
|
126
|
+
| MUST DO | MUST NOT DO |
|
|
127
|
+
|---------|-------------|
|
|
128
|
+
| Check every scenario individually | Sample scenarios and extrapolate |
|
|
129
|
+
| Apply slot-level rules strictly per the ownership table | Accept executor slots for integration scenarios "because it is simpler" |
|
|
130
|
+
| Report slot-stack mismatch separately from slot-level mismatch | Combine into one finding when both violations exist on the same scenario |
|
|
131
|
+
| Set all three target fields on every TDD finding | Use null targets for locatable violations |
|
|
132
|
+
| Complete all five checks before emitting findings | Stop after discovering Check 1 failures |
|
|
133
|
+
|
|
134
|
+
## Final Checklist
|
|
135
|
+
|
|
136
|
+
- [ ] All five checks executed for every scenario
|
|
137
|
+
- [ ] Every `unit` scenario uses an executor slot matching its stack
|
|
138
|
+
- [ ] Every `integration` scenario uses a tester slot matching its stack
|
|
139
|
+
- [ ] Every `e2e` scenario uses a tester or domain-reviewer slot matching its stack
|
|
140
|
+
- [ ] Every scenario's first step is a failing test
|
|
141
|
+
- [ ] No implementation step precedes the red-test step in any scenario
|
|
142
|
+
- [ ] Every finding targets a specific scenario with all three target fields populated
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultraplan-scout
|
|
3
|
+
description: Codebase reconnaissance stage — maps reusable assets, integration points, conventions, and test patterns for each applicable stack
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UltraPlan Scout
|
|
7
|
+
|
|
8
|
+
Perform structured codebase reconnaissance and write findings as a JSON artifact. This stage runs after intake and before discover. It provides the factual foundation that all later stages depend on.
|
|
9
|
+
|
|
10
|
+
## Quick Reference
|
|
11
|
+
|
|
12
|
+
| Aspect | Detail |
|
|
13
|
+
|--------|--------|
|
|
14
|
+
| **Inputs** | Intake artifact (provided by pipeline runner); repo access |
|
|
15
|
+
| **Output** | Scout artifact written via `ultraplan_scout_record` |
|
|
16
|
+
| **Tools** | `task`, `search`, `find`, `read`, `lsp` |
|
|
17
|
+
| **Scope** | Read-only. No edits. No inferences beyond what is observed. |
|
|
18
|
+
| **Storage tool** | `ultraplan_scout_record` — called exactly once |
|
|
19
|
+
|
|
20
|
+
## Reconnaissance Areas
|
|
21
|
+
|
|
22
|
+
For each stack marked `applicable` or `unknown` in the intake artifact, you MUST gather findings in all five areas below. For stacks marked `not-applicable`, skip them.
|
|
23
|
+
|
|
24
|
+
### 1. Reusable Assets
|
|
25
|
+
|
|
26
|
+
- Shared utilities, hooks, middleware, helper functions, base classes
|
|
27
|
+
- Existing abstractions in the relevant stack directory (e.g. `src/`, `app/`, `server/`, `infra/`)
|
|
28
|
+
- Package dependencies (read `package.json`, `pyproject.toml`, `go.mod`, etc.)
|
|
29
|
+
|
|
30
|
+
### 2. Integration Points
|
|
31
|
+
|
|
32
|
+
- Entry points, route handlers, API boundaries, event emitters, message queues
|
|
33
|
+
- Shared state surfaces (databases, caches, shared configs)
|
|
34
|
+
- Cross-stack interfaces (e.g. REST contracts, gRPC definitions, shared types)
|
|
35
|
+
|
|
36
|
+
### 3. Conventions
|
|
37
|
+
|
|
38
|
+
- Directory structure and file naming patterns
|
|
39
|
+
- Module/import patterns (path aliases, barrel exports, index files)
|
|
40
|
+
- Error handling patterns (Result types, thrown exceptions, error middleware)
|
|
41
|
+
- Coding style signals (linting config, tsconfig settings, eslint rules)
|
|
42
|
+
|
|
43
|
+
### 4. Existing Test Patterns
|
|
44
|
+
|
|
45
|
+
- Test runner and framework in use (Jest, Vitest, pytest, Go test, etc.)
|
|
46
|
+
- Test file location conventions (`__tests__/`, `.test.ts`, `_test.go`, etc.)
|
|
47
|
+
- Fixture and factory patterns
|
|
48
|
+
- Coverage configuration and thresholds
|
|
49
|
+
|
|
50
|
+
### 5. Gotchas
|
|
51
|
+
|
|
52
|
+
- Deprecated modules or patterns in active use
|
|
53
|
+
- Known workarounds or TODO comments in relevant files
|
|
54
|
+
- Circular dependencies or architectural debts visible from file structure
|
|
55
|
+
- Missing abstractions that multiple callers work around
|
|
56
|
+
|
|
57
|
+
## Investigation Strategy
|
|
58
|
+
|
|
59
|
+
Use `find` to map structure before reading individual files. Use `search` to locate patterns (error handlers, test factories, shared types). Use `read` for targeted file reads. Use `lsp` to follow type definitions and usages. Delegate broad parallel investigations to `task`.
|
|
60
|
+
|
|
61
|
+
Do not read entire files unless necessary. Read only the sections relevant to each reconnaissance area.
|
|
62
|
+
|
|
63
|
+
## Output Schema
|
|
64
|
+
|
|
65
|
+
Call `ultraplan_scout_record` exactly once with:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
ultraplan_scout_record({
|
|
69
|
+
stacks: {
|
|
70
|
+
[stackId: "frontend" | "backend" | "infrastructure"]: {
|
|
71
|
+
reusableAssets: string[], // file paths or symbol names
|
|
72
|
+
integrationPoints: string[], // file paths or description strings
|
|
73
|
+
conventions: {
|
|
74
|
+
directories: string[],
|
|
75
|
+
naming: string,
|
|
76
|
+
errorHandling: string,
|
|
77
|
+
importStyle: string
|
|
78
|
+
},
|
|
79
|
+
testPatterns: {
|
|
80
|
+
runner: string,
|
|
81
|
+
fileConvention: string,
|
|
82
|
+
fixturePattern: string | null,
|
|
83
|
+
coverageConfig: string | null
|
|
84
|
+
},
|
|
85
|
+
gotchas: string[]
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
crossCuttingConcerns: string[] // patterns that span multiple stacks
|
|
89
|
+
})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Report only what was observed. Use `null` for fields where no evidence was found.
|
|
93
|
+
|
|
94
|
+
## MUST DO / MUST NOT DO
|
|
95
|
+
|
|
96
|
+
| MUST DO | MUST NOT DO |
|
|
97
|
+
|---------|-------------|
|
|
98
|
+
| Investigate every applicable and unknown stack | Skip stacks because they seem unrelated to the goal |
|
|
99
|
+
| Report file paths as evidence for every asset and integration point | Make assertions without observed evidence |
|
|
100
|
+
| Use `null` for fields with no evidence | Invent conventions or test patterns |
|
|
101
|
+
| Parallelize independent stack investigations via `task` | Read files serially when parallel is safe |
|
|
102
|
+
| Call `ultraplan_scout_record` exactly once | Write narrative prose instead of structured JSON |
|
|
103
|
+
|
|
104
|
+
## Final Checklist
|
|
105
|
+
|
|
106
|
+
- [ ] Every applicable/unknown stack has entries in all five reconnaissance areas
|
|
107
|
+
- [ ] Every asset and integration point has a file path or symbol name as evidence
|
|
108
|
+
- [ ] `crossCuttingConcerns` captured where applicable
|
|
109
|
+
- [ ] `ultraplan_scout_record` called exactly once
|
|
110
|
+
- [ ] No edits made to any file
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ultraplan-synthesize
|
|
3
|
+
description: Scenario decomposition stage — produces a complete authored.json and manifest.json draft from all prior pipeline artifacts
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UltraPlan Synthesize
|
|
7
|
+
|
|
8
|
+
Decompose the intake goal into executable scenarios with TDD ownership, slot assignments, and dependency edges. This stage runs after all research artifacts are available. Its output is the plan draft submitted to the review checkers.
|
|
9
|
+
|
|
10
|
+
## Quick Reference
|
|
11
|
+
|
|
12
|
+
| Aspect | Detail |
|
|
13
|
+
|--------|--------|
|
|
14
|
+
| **Inputs** | Intake + scout + discover + all research artifacts (provided by pipeline runner) |
|
|
15
|
+
| **Output** | Authored draft written via `ultraplan_synth_draft` |
|
|
16
|
+
| **Scope** | All applicable stacks; every intake success criterion must map to ≥1 scenario |
|
|
17
|
+
| **Storage tool** | `ultraplan_synth_draft({ authored, manifest })` — called exactly once |
|
|
18
|
+
|
|
19
|
+
## Structural Rules
|
|
20
|
+
|
|
21
|
+
These rules are enforced by the structure-checker. Violating them produces BLOCKER findings.
|
|
22
|
+
|
|
23
|
+
| Rule | Constraint |
|
|
24
|
+
|------|-----------|
|
|
25
|
+
| Stack coverage | Every applicable stack has ≥1 domain |
|
|
26
|
+
| Domain coverage | Every domain has ≥1 scenario |
|
|
27
|
+
| Scenario fields | Every scenario has: `id`, `title`, `level`, `slot`, `steps`, `dependencies` |
|
|
28
|
+
| ID uniqueness | All scenario IDs are unique across all stacks and domains |
|
|
29
|
+
| Dependency graph | No cycles — if A depends on B, B must not depend on A (directly or transitively) |
|
|
30
|
+
| Intake coverage | Every intake success criterion maps to ≥1 scenario (checked by scope-checker) |
|
|
31
|
+
|
|
32
|
+
## TDD Ownership Rules
|
|
33
|
+
|
|
34
|
+
These rules are enforced by the tdd-checker. Violating them produces BLOCKER findings.
|
|
35
|
+
|
|
36
|
+
| Level | Owning slot | Proof obligation |
|
|
37
|
+
|-------|-------------|-----------------|
|
|
38
|
+
| `unit` | `backend-executor`, `frontend-executor`, or `infrastructure-executor` | Red test committed before implementation |
|
|
39
|
+
| `integration` | `backend-tester`, `frontend-tester`, or `infrastructure-tester` | Red test committed; covers cross-boundary behavior |
|
|
40
|
+
| `e2e` | `backend-tester`, `frontend-tester`, `infrastructure-tester`, or `*-domain-reviewer` | Red test committed; simulates end-user flow |
|
|
41
|
+
|
|
42
|
+
Every scenario marked `level: unit` MUST have a `steps` entry that creates and runs a failing test before implementation. Every scenario at `integration` or `e2e` MUST have a `steps` entry that writes and runs the failing test as its first step.
|
|
43
|
+
|
|
44
|
+
## Decomposition Process
|
|
45
|
+
|
|
46
|
+
### Step 1 — Map intake success criteria to domains
|
|
47
|
+
|
|
48
|
+
Group success criteria into logical domains per stack. A domain is a coherent capability boundary (e.g. "authentication", "billing", "data-export"). Avoid single-scenario domains unless the capability genuinely stands alone.
|
|
49
|
+
|
|
50
|
+
### Step 2 — Decompose each domain into scenarios
|
|
51
|
+
|
|
52
|
+
A scenario is the smallest independently verifiable unit of work. Split along these seams:
|
|
53
|
+
- Happy path vs error path (separate scenarios if the error path requires different test setup)
|
|
54
|
+
- Read vs write (if they have independent validation requirements)
|
|
55
|
+
- Sync vs async (if they have different timing constraints)
|
|
56
|
+
|
|
57
|
+
Do not split for its own sake. If two behaviors are always tested together, they belong in one scenario.
|
|
58
|
+
|
|
59
|
+
### Step 3 — Assign levels and slots
|
|
60
|
+
|
|
61
|
+
Apply TDD ownership rules. When a scenario touches multiple stacks, assign it to the stack that owns the primary side effect.
|
|
62
|
+
|
|
63
|
+
### Step 4 — Order dependencies
|
|
64
|
+
|
|
65
|
+
Mark `dependencies` as a list of scenario IDs that must be complete before this scenario can begin. Use `[]` for no dependencies. Verify there are no cycles.
|
|
66
|
+
|
|
67
|
+
### Step 5 — Write the draft
|
|
68
|
+
|
|
69
|
+
Call `ultraplan_synth_draft` exactly once:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
ultraplan_synth_draft({
|
|
73
|
+
authored: {
|
|
74
|
+
stacks: [
|
|
75
|
+
{
|
|
76
|
+
id: "frontend" | "backend" | "infrastructure",
|
|
77
|
+
domains: [
|
|
78
|
+
{
|
|
79
|
+
id: string,
|
|
80
|
+
name: string,
|
|
81
|
+
scenarios: [
|
|
82
|
+
{
|
|
83
|
+
id: string,
|
|
84
|
+
title: string,
|
|
85
|
+
level: "unit" | "integration" | "e2e",
|
|
86
|
+
slot: string, // e.g. "backend-executor"
|
|
87
|
+
steps: string[], // imperative steps; first step writes failing test
|
|
88
|
+
dependencies: string[] // scenario IDs
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
manifest: {
|
|
97
|
+
title: string,
|
|
98
|
+
goal: string,
|
|
99
|
+
successCriteria: string[],
|
|
100
|
+
deferredIdeas: string[]
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## MUST DO / MUST NOT DO
|
|
106
|
+
|
|
107
|
+
| MUST DO | MUST NOT DO |
|
|
108
|
+
|---------|-------------|
|
|
109
|
+
| Map every intake success criterion to ≥1 scenario | Generate scenarios with no connection to the intake goal |
|
|
110
|
+
| Assign `unit` scenarios to executor slots | Assign `unit` scenarios to tester slots |
|
|
111
|
+
| Make the first step of every scenario a failing test | Write implementation steps before a test step |
|
|
112
|
+
| Verify no dependency cycles before calling `ultraplan_synth_draft` | Produce a cyclic dependency graph |
|
|
113
|
+
| Cover every applicable stack with ≥1 domain | Leave an applicable stack with no scenarios |
|
|
114
|
+
|
|
115
|
+
## Final Checklist
|
|
116
|
+
|
|
117
|
+
- [ ] Every intake success criterion maps to ≥1 scenario
|
|
118
|
+
- [ ] Every applicable stack has ≥1 domain with ≥1 scenario
|
|
119
|
+
- [ ] Every scenario has all required fields
|
|
120
|
+
- [ ] All scenario IDs are unique
|
|
121
|
+
- [ ] All `unit` scenarios use executor slots; all `integration`/`e2e` use tester or domain-reviewer slots
|
|
122
|
+
- [ ] Every scenario's first step creates a failing test
|
|
123
|
+
- [ ] Dependency graph is acyclic (verified by inspection)
|
|
124
|
+
- [ ] `ultraplan_synth_draft` called exactly once
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
// src/ai/final-message.ts
|
|
2
|
+
//
|
|
3
|
+
// Generic helpers for running a one-shot structured agent session and
|
|
4
|
+
// extracting the final assistant message. Lives under src/ai/ because it has
|
|
5
|
+
// no dependencies on review, planning, quality, or any other workflow.
|
|
6
|
+
//
|
|
7
|
+
// Consumers:
|
|
8
|
+
// - src/ai/structured-output.ts (the schema-backed retry loop)
|
|
9
|
+
// - src/quality/gates/ai-review.ts, src/quality/ai-setup.ts (one-shot AI)
|
|
10
|
+
// - src/lsp/bridge.ts, src/docs/drift.ts, src/commands/release.ts
|
|
11
|
+
//
|
|
12
|
+
// Phase 5 / P7B will migrate the remaining one-shot consumers to the schema-
|
|
13
|
+
// backed runner; until then, runStructuredAgentSession is the lowest-level
|
|
14
|
+
// shared primitive.
|
|
15
|
+
|
|
1
16
|
import type { GateExecutionContext } from "../types.js";
|
|
2
17
|
|
|
3
18
|
export interface StructuredAgentRunOptions {
|
|
@@ -5,6 +20,8 @@ export interface StructuredAgentRunOptions {
|
|
|
5
20
|
prompt: string;
|
|
6
21
|
model?: string;
|
|
7
22
|
thinkingLevel?: string | null;
|
|
23
|
+
agentId?: string;
|
|
24
|
+
agentDisplayName?: string;
|
|
8
25
|
timeoutMs?: number;
|
|
9
26
|
}
|
|
10
27
|
|
|
@@ -39,6 +56,10 @@ function extractTextFromContent(content: unknown): string {
|
|
|
39
56
|
return "";
|
|
40
57
|
}
|
|
41
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Walk the message list backwards and return the last assistant message text.
|
|
61
|
+
* Returns null when no assistant message contains usable text.
|
|
62
|
+
*/
|
|
42
63
|
export function extractFinalAssistantText(messages: unknown[]): string | null {
|
|
43
64
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
44
65
|
const message = messages[index];
|
|
@@ -61,6 +82,10 @@ export function extractFinalAssistantText(messages: unknown[]): string | null {
|
|
|
61
82
|
return null;
|
|
62
83
|
}
|
|
63
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Run a one-shot agent session and return the final assistant message text.
|
|
87
|
+
* Disposes the session whether the prompt succeeds or throws.
|
|
88
|
+
*/
|
|
64
89
|
export async function runStructuredAgentSession(
|
|
65
90
|
createAgentSession: GateExecutionContext["createAgentSession"],
|
|
66
91
|
options: StructuredAgentRunOptions,
|
|
@@ -69,6 +94,8 @@ export async function runStructuredAgentSession(
|
|
|
69
94
|
cwd: options.cwd,
|
|
70
95
|
model: options.model,
|
|
71
96
|
thinkingLevel: options.thinkingLevel ?? null,
|
|
97
|
+
...(options.agentId ? { agentId: options.agentId } : {}),
|
|
98
|
+
...(options.agentDisplayName ? { agentDisplayName: options.agentDisplayName } : {}),
|
|
72
99
|
});
|
|
73
100
|
|
|
74
101
|
try {
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/ai/schema-text.ts
|
|
2
|
+
//
|
|
3
|
+
// Render a TypeBox schema as compact TS-like text suitable for embedding in
|
|
4
|
+
// prompts. One canonical rendering means that adding a field to a TypeBox
|
|
5
|
+
// contract automatically updates every prompt that references it through
|
|
6
|
+
// this module — no hand-maintained schema prose to drift.
|
|
7
|
+
//
|
|
8
|
+
// Consumers:
|
|
9
|
+
// - src/review/* (runner, multi-agent-runner, validator, fixer) render
|
|
10
|
+
// ReviewOutputSchema / ReviewFixOutputSchema for both the main prompt
|
|
11
|
+
// and the retry prompt produced by runWithOutputValidation.
|
|
12
|
+
//
|
|
13
|
+
// Non-goals:
|
|
14
|
+
// - Produce standards-compliant JSON Schema output. Use TypeBox's own
|
|
15
|
+
// JSON Schema accessors for that. This renderer optimises for model
|
|
16
|
+
// readability, not spec compliance.
|
|
17
|
+
// - Capture every TypeBox modifier. Supported shapes cover the current
|
|
18
|
+
// contract surface; extend when a real consumer needs more.
|
|
19
|
+
|
|
20
|
+
import type { TSchema } from "@sinclair/typebox";
|
|
21
|
+
|
|
22
|
+
const INDENT = " ";
|
|
23
|
+
|
|
24
|
+
export interface RenderSchemaOptions {
|
|
25
|
+
/** Start indent (internal recursion use). */
|
|
26
|
+
depth?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function indent(depth: number): string {
|
|
30
|
+
return INDENT.repeat(depth);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function renderLiteral(value: unknown): string {
|
|
34
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
35
|
+
if (value === null) return "null";
|
|
36
|
+
return String(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function renderUnion(parts: readonly TSchema[], depth: number): string {
|
|
40
|
+
if (parts.length === 0) return "never";
|
|
41
|
+
return parts.map((p) => renderSchemaText(p, { depth })).join(" | ");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function renderObject(schema: any, depth: number): string {
|
|
45
|
+
const props = schema.properties as Record<string, TSchema> | undefined;
|
|
46
|
+
if (!props || Object.keys(props).length === 0) {
|
|
47
|
+
return "{}";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const required: string[] = Array.isArray(schema.required) ? schema.required : [];
|
|
51
|
+
const lines: string[] = ["{"];
|
|
52
|
+
const childDepth = depth + 1;
|
|
53
|
+
|
|
54
|
+
for (const [key, child] of Object.entries(props)) {
|
|
55
|
+
const isRequired = required.includes(key);
|
|
56
|
+
const separator = isRequired ? ":" : "?:";
|
|
57
|
+
lines.push(`${indent(childDepth)}${key}${separator} ${renderSchemaText(child, { depth: childDepth })};`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
lines.push(`${indent(depth)}}`);
|
|
61
|
+
return lines.join("\n");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function renderArray(schema: any, depth: number): string {
|
|
65
|
+
const inner = renderSchemaText(schema.items as TSchema, { depth });
|
|
66
|
+
// Wrap multiline object types as Array<...> for readability.
|
|
67
|
+
if (inner.includes("\n")) {
|
|
68
|
+
return `Array<${inner}>`;
|
|
69
|
+
}
|
|
70
|
+
return `${inner}[]`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function hasKey(schema: any, key: string): boolean {
|
|
74
|
+
return schema != null && typeof schema === "object" && key in schema;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Render a TypeBox schema as a compact TS-like type string. Safe to pass as
|
|
79
|
+
* the `schema:` param to `runWithOutputValidation` and the `{{outputSchema}}`
|
|
80
|
+
* placeholder inside review prompts.
|
|
81
|
+
*/
|
|
82
|
+
export function renderSchemaText(schema: TSchema, options: RenderSchemaOptions = {}): string {
|
|
83
|
+
const depth = options.depth ?? 0;
|
|
84
|
+
const any = schema as any;
|
|
85
|
+
|
|
86
|
+
// Literal / const
|
|
87
|
+
if (hasKey(any, "const")) {
|
|
88
|
+
return renderLiteral(any.const);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Explicit enum
|
|
92
|
+
if (Array.isArray(any.enum)) {
|
|
93
|
+
return any.enum.map(renderLiteral).join(" | ");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Union (anyOf / oneOf)
|
|
97
|
+
if (Array.isArray(any.anyOf)) {
|
|
98
|
+
return renderUnion(any.anyOf, depth);
|
|
99
|
+
}
|
|
100
|
+
if (Array.isArray(any.oneOf)) {
|
|
101
|
+
return renderUnion(any.oneOf, depth);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Primitive / structural by `type`
|
|
105
|
+
const type = any.type as string | undefined;
|
|
106
|
+
switch (type) {
|
|
107
|
+
case "object":
|
|
108
|
+
return renderObject(any, depth);
|
|
109
|
+
case "array":
|
|
110
|
+
return renderArray(any, depth);
|
|
111
|
+
case "string":
|
|
112
|
+
return "string";
|
|
113
|
+
case "integer":
|
|
114
|
+
return "integer";
|
|
115
|
+
case "number":
|
|
116
|
+
return "number";
|
|
117
|
+
case "boolean":
|
|
118
|
+
return "boolean";
|
|
119
|
+
case "null":
|
|
120
|
+
return "null";
|
|
121
|
+
default:
|
|
122
|
+
// Fall through — unknown shape
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Nothing matched — render as `unknown` rather than throwing so prompts
|
|
127
|
+
// still get something readable if someone adds an exotic schema.
|
|
128
|
+
return "unknown";
|
|
129
|
+
}
|