ultra-builder-pro-cli 0.10.0 → 0.12.1
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/.ultra-template/specs/architecture.md +54 -223
- package/.ultra-template/specs/discovery.md +34 -231
- package/.ultra-template/specs/product.md +44 -200
- package/.ultra-template/tasks/contexts/TEMPLATE.md +36 -0
- package/.ultra-template/tasks/tasks.json +6 -0
- package/CHANGELOG.md +86 -1
- package/README.md +21 -9
- package/adapters/_shared/codex-assets.cjs +24 -342
- package/adapters/_shared/handbook.cjs +4 -3
- package/adapters/_shared/runtime-assets.cjs +24 -0
- package/adapters/_shared/tests/handbook.test.cjs +4 -0
- package/adapters/_shared/tests/runtime-assets.test.cjs +11 -4
- package/adapters/claude.js +28 -5
- package/adapters/kimi.js +15 -138
- package/adapters/opencode.js +22 -49
- package/adapters/tests/claude.test.cjs +22 -8
- package/adapters/tests/codex.test.cjs +21 -8
- package/adapters/tests/kimi-hook.test.cjs +1 -1
- package/adapters/tests/kimi.test.cjs +11 -11
- package/adapters/tests/opencode.test.cjs +47 -8
- package/agents/code-reviewer.md +24 -85
- package/agents/debugger.md +30 -132
- package/agents/review-code.md +24 -104
- package/agents/review-comments.md +20 -83
- package/agents/review-coordinator.md +40 -137
- package/agents/review-design.md +21 -118
- package/agents/review-errors.md +22 -70
- package/agents/review-spec.md +36 -0
- package/agents/review-tests.md +20 -76
- package/agents/tdd-runner.md +26 -84
- package/commands/learn.md +5 -36
- package/commands/ultra-change.md +5 -43
- package/commands/ultra-deliver.md +4 -46
- package/commands/ultra-dev.md +4 -48
- package/commands/ultra-doctor.md +4 -30
- package/commands/ultra-init.md +5 -47
- package/commands/ultra-plan.md +5 -48
- package/commands/ultra-research.md +5 -54
- package/commands/ultra-status.md +5 -44
- package/commands/ultra-test.md +5 -45
- package/commands/ultra-think.md +5 -40
- package/docs/AGENT-CONTEXT.md +16 -8
- package/docs/ARCHITECTURE.md +32 -5
- package/docs/PLAN.zh-CN.md +8 -6
- package/docs/ROADMAP.md +5 -3
- package/docs/RUNTIME-COMPAT-MATRIX.md +8 -5
- package/docs/SKILL-AUTHORING.md +75 -0
- package/docs/STATE-DB-ACCESS-POLICY.md +17 -11
- package/docs/USER-HANDBOOK-CONTRACT.md +8 -5
- package/hooks/README.md +4 -3
- package/hooks/adapters/codex.py +1 -1
- package/hooks/adapters/kimi.py +1 -1
- package/hooks/context_spine.py +120 -16
- package/hooks/health_check.py +11 -0
- package/hooks/pre_stop_check.py +6 -5
- package/mcp-server/lib/baseline-workflow.cjs +415 -0
- package/mcp-server/lib/baseline-workflow.test.cjs +225 -0
- package/mcp-server/lib/change-workflow.cjs +24 -27
- package/mcp-server/lib/change-workflow.test.cjs +202 -6
- package/mcp-server/lib/context-spine.cjs +74 -9
- package/mcp-server/lib/context-spine.test.cjs +15 -0
- package/mcp-server/lib/doctor.cjs +14 -0
- package/mcp-server/lib/doctor.test.cjs +25 -1
- package/mcp-server/lib/init-project.cjs +49 -14
- package/mcp-server/lib/provider-refs.cjs +42 -0
- package/mcp-server/lib/spec-learning.test.cjs +5 -0
- package/mcp-server/lib/state-db.cjs +63 -4
- package/mcp-server/lib/state-db.test.cjs +8 -3
- package/mcp-server/server.cjs +48 -3
- package/mcp-server/tests/init-project.test.cjs +54 -8
- package/mcp-server/tests/server-contract.test.cjs +99 -2
- package/mcp-server/tests/state-db.test.cjs +11 -2
- package/package.json +3 -2
- package/skills/cc-collab/SKILL.md +16 -18
- package/skills/code-review-expert/SKILL.md +39 -114
- package/skills/code-review-expert/references/correctness-reliability.md +30 -0
- package/skills/code-review-expert/references/design-boundaries.md +26 -0
- package/skills/code-review-expert/references/removal-plan.md +17 -45
- package/skills/codex-collab/SKILL.md +23 -28
- package/skills/codex-collab/evals/evals.json +18 -23
- package/skills/integration-rules/SKILL.md +28 -67
- package/skills/learn/SKILL.md +46 -106
- package/skills/security-rules/SKILL.md +34 -56
- package/skills/testing-rules/SKILL.md +28 -52
- package/skills/ultra-change/SKILL.md +68 -114
- package/skills/ultra-deliver/SKILL.md +58 -86
- package/skills/ultra-dev/SKILL.md +46 -105
- package/skills/ultra-doctor/SKILL.md +45 -72
- package/skills/ultra-init/SKILL.md +62 -147
- package/skills/ultra-init/references/brownfield-adoption.md +65 -0
- package/skills/ultra-plan/SKILL.md +56 -89
- package/skills/ultra-research/SKILL.md +64 -152
- package/skills/ultra-research/references/architecture.md +38 -0
- package/skills/ultra-research/references/problem-product.md +39 -0
- package/skills/ultra-research/references/quality-delivery.md +34 -0
- package/skills/ultra-research/references/synthesis.md +38 -0
- package/skills/ultra-research/references/users-scope.md +40 -0
- package/skills/ultra-review/SKILL.md +54 -98
- package/skills/ultra-review/references/unified-schema.md +76 -101
- package/skills/ultra-review/scripts/review_wait.py +242 -77
- package/skills/ultra-status/SKILL.md +41 -56
- package/skills/ultra-test/SKILL.md +37 -72
- package/skills/ultra-think/SKILL.md +43 -102
- package/skills/ultra-verify/SKILL.md +44 -84
- package/skills/ultra-verify/evals/evals.json +24 -27
- package/spec/cli-protocol.md +4 -0
- package/spec/mcp-tools.yaml +223 -4
- package/spec/schemas/command-manifest.schema.json +7 -25
- package/spec/schemas/mcp-tools.schema.json +1 -1
- package/spec/schemas/skill-manifest.schema.json +9 -79
- package/spec/schemas/state-db.sql +33 -2
- package/ultra-tools/commands/status.cjs +20 -2
- package/ultra-tools/commands/task.cjs +4 -1
- package/ultra-tools/status-command.test.cjs +20 -0
- package/ultra-tools/system-command.test.cjs +5 -0
- package/skills/code-review-expert/references/code-quality-checklist.md +0 -112
- package/skills/code-review-expert/references/integration-checklist.md +0 -46
- package/skills/code-review-expert/references/security-checklist.md +0 -100
- package/skills/code-review-expert/references/solid-checklist.md +0 -65
- package/skills/ultra-research/steps/step-00-problem-validation.md +0 -154
- package/skills/ultra-research/steps/step-01-opportunity-discovery.md +0 -172
- package/skills/ultra-research/steps/step-02-market-assessment.md +0 -195
- package/skills/ultra-research/steps/step-03-competitive-landscape.md +0 -197
- package/skills/ultra-research/steps/step-04-product-strategy.md +0 -196
- package/skills/ultra-research/steps/step-05-assumptions-validation.md +0 -234
- package/skills/ultra-research/steps/step-10-user-personas.md +0 -169
- package/skills/ultra-research/steps/step-11-user-scenarios.md +0 -181
- package/skills/ultra-research/steps/step-20-user-stories.md +0 -156
- package/skills/ultra-research/steps/step-21-features-scope.md +0 -157
- package/skills/ultra-research/steps/step-22-success-metrics.md +0 -195
- package/skills/ultra-research/steps/step-30-architecture-context.md +0 -154
- package/skills/ultra-research/steps/step-31-solution-strategy.md +0 -172
- package/skills/ultra-research/steps/step-32-building-blocks.md +0 -188
- package/skills/ultra-research/steps/step-40-deployment.md +0 -123
- package/skills/ultra-research/steps/step-41-quality-risks.md +0 -135
- package/skills/ultra-research/steps/step-99-synthesis.md +0 -188
- package/skills/ultra-review/scripts/review_verdict_update.py +0 -99
package/spec/cli-protocol.md
CHANGED
|
@@ -100,6 +100,10 @@ as a fallback unless `ultra-tools <family> --help` lists it.
|
|
|
100
100
|
| `session.admission_check` | `session admission` | 4.5 | any |
|
|
101
101
|
| `session.heartbeat` | `session heartbeat` | 4.5 | mcp |
|
|
102
102
|
| `session.subscribe_events`| `session subscribe` | 4.5 | any |
|
|
103
|
+
| `baseline.start` | `baseline start` | 11 | mcp |
|
|
104
|
+
| `baseline.record` | `baseline record` | 11 | mcp |
|
|
105
|
+
| `baseline.get` | `baseline get` | 11 | any |
|
|
106
|
+
| `baseline.converge` | `baseline converge` | 11 | mcp |
|
|
103
107
|
| `change.create` | `change create` | 9 | mcp |
|
|
104
108
|
| `change.update` | `change update` | 9 | mcp |
|
|
105
109
|
| `change.get` | `change get` | 9 | any |
|
package/spec/mcp-tools.yaml
CHANGED
|
@@ -23,6 +23,7 @@ families:
|
|
|
23
23
|
- { name: task, description: 'authoritative task lifecycle on state.db', phase: '2' }
|
|
24
24
|
- { name: session, description: 'execution-unit lifecycle with single-active-lease admission (D33)', phase: '4.5' }
|
|
25
25
|
- { name: plan, description: 'execution-plan artifact export and query (D34)', phase: '8a' }
|
|
26
|
+
- { name: baseline, description: 'project adoption, baseline evidence, convergence, and drift authority', phase: '11' }
|
|
26
27
|
- { name: change, description: 'continuous post-delivery change lifecycle and convergence', phase: '9' }
|
|
27
28
|
- { name: system, description: 'read-only diagnostics and explicit backup-first repair', phase: '9' }
|
|
28
29
|
|
|
@@ -217,9 +218,9 @@ tools:
|
|
|
217
218
|
- name: task.init_project
|
|
218
219
|
family: task
|
|
219
220
|
description: |
|
|
220
|
-
Bootstrap
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
Bootstrap `.ultra/` and start an authoritative greenfield or brownfield
|
|
222
|
+
baseline. Auto mode detects meaningful existing project content before
|
|
223
|
+
copying specification templates and creating state.db.
|
|
223
224
|
phase: '3'
|
|
224
225
|
writer_role: mcp
|
|
225
226
|
input_schema:
|
|
@@ -240,6 +241,11 @@ tools:
|
|
|
240
241
|
stack:
|
|
241
242
|
type: string
|
|
242
243
|
description: optional tech stack descriptor (comma-separated for fullstack)
|
|
244
|
+
mode:
|
|
245
|
+
type: string
|
|
246
|
+
enum: [auto, greenfield, brownfield]
|
|
247
|
+
default: auto
|
|
248
|
+
description: auto detects whether meaningful project content already exists
|
|
243
249
|
overwrite:
|
|
244
250
|
type: boolean
|
|
245
251
|
default: false
|
|
@@ -249,7 +255,7 @@ tools:
|
|
|
249
255
|
description: override path to the template root (defaults to bundled templates/.ultra/)
|
|
250
256
|
output_schema:
|
|
251
257
|
type: object
|
|
252
|
-
required: [created_path, state_db_path, status, copied_files]
|
|
258
|
+
required: [created_path, state_db_path, status, mode, baseline, copied_files]
|
|
253
259
|
additionalProperties: false
|
|
254
260
|
properties:
|
|
255
261
|
created_path:
|
|
@@ -261,6 +267,13 @@ tools:
|
|
|
261
267
|
status:
|
|
262
268
|
type: string
|
|
263
269
|
enum: [created, overwritten]
|
|
270
|
+
mode:
|
|
271
|
+
type: string
|
|
272
|
+
enum: [greenfield, brownfield]
|
|
273
|
+
baseline:
|
|
274
|
+
type: object
|
|
275
|
+
required: [id, mode, status]
|
|
276
|
+
additionalProperties: true
|
|
264
277
|
copied_files:
|
|
265
278
|
type: array
|
|
266
279
|
items: { type: string }
|
|
@@ -629,6 +642,210 @@ tools:
|
|
|
629
642
|
emits_events: []
|
|
630
643
|
trace_to: '§7.3, D31'
|
|
631
644
|
|
|
645
|
+
# ───────────────────────── baseline family ─────────────────────────────
|
|
646
|
+
- name: baseline.start
|
|
647
|
+
family: baseline
|
|
648
|
+
description: Start a greenfield baseline or brownfield adoption without overwriting a ready baseline implicitly.
|
|
649
|
+
phase: '11'
|
|
650
|
+
writer_role: mcp
|
|
651
|
+
input_schema:
|
|
652
|
+
type: object
|
|
653
|
+
required: [project_name, mode]
|
|
654
|
+
additionalProperties: false
|
|
655
|
+
properties:
|
|
656
|
+
id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$', default: project-baseline }
|
|
657
|
+
project_name: { type: string, minLength: 1 }
|
|
658
|
+
project_type: { type: string, enum: [web, api, cli, fullstack, other] }
|
|
659
|
+
stack: { type: string }
|
|
660
|
+
mode: { type: string, enum: [greenfield, brownfield] }
|
|
661
|
+
scope: { type: array, minItems: 1, items: { type: string, minLength: 1 }, default: ['.'] }
|
|
662
|
+
repository_revision: { type: string, minLength: 1 }
|
|
663
|
+
replace_ready: { type: boolean, default: false }
|
|
664
|
+
provider_refs:
|
|
665
|
+
type: object
|
|
666
|
+
additionalProperties: false
|
|
667
|
+
properties:
|
|
668
|
+
memory:
|
|
669
|
+
type: object
|
|
670
|
+
required: [provider]
|
|
671
|
+
additionalProperties: false
|
|
672
|
+
properties:
|
|
673
|
+
provider: { type: string }
|
|
674
|
+
project: { type: string }
|
|
675
|
+
reference: { type: string }
|
|
676
|
+
revision: { type: string }
|
|
677
|
+
indexed_head: { type: string }
|
|
678
|
+
status: { type: string, enum: [available, unavailable, fresh, stale, unknown] }
|
|
679
|
+
code_graph:
|
|
680
|
+
type: object
|
|
681
|
+
required: [provider]
|
|
682
|
+
additionalProperties: false
|
|
683
|
+
properties:
|
|
684
|
+
provider: { type: string }
|
|
685
|
+
project: { type: string }
|
|
686
|
+
reference: { type: string }
|
|
687
|
+
revision: { type: string }
|
|
688
|
+
indexed_head: { type: string }
|
|
689
|
+
status: { type: string, enum: [available, unavailable, fresh, stale, unknown] }
|
|
690
|
+
output_schema:
|
|
691
|
+
type: object
|
|
692
|
+
required: [baseline]
|
|
693
|
+
additionalProperties: false
|
|
694
|
+
properties:
|
|
695
|
+
baseline: { type: object }
|
|
696
|
+
errors:
|
|
697
|
+
- { code: BASELINE_EXISTS, description: 'a ready baseline requires explicit replacement' }
|
|
698
|
+
- { code: BASELINE_IN_PROGRESS, description: 'another adoption is already active' }
|
|
699
|
+
- { code: PROVIDER_CONTENT_FORBIDDEN, description: 'provider payload content must remain external' }
|
|
700
|
+
cli_subcommand: baseline start
|
|
701
|
+
emits_events: [baseline_started]
|
|
702
|
+
|
|
703
|
+
- name: baseline.record
|
|
704
|
+
family: baseline
|
|
705
|
+
description: Replace the current adoption snapshot with bounded specification digests, evidence references, verification, unknowns, and provider metadata.
|
|
706
|
+
phase: '11'
|
|
707
|
+
writer_role: mcp
|
|
708
|
+
input_schema:
|
|
709
|
+
type: object
|
|
710
|
+
required: [id]
|
|
711
|
+
additionalProperties: false
|
|
712
|
+
properties:
|
|
713
|
+
id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$' }
|
|
714
|
+
repository_revision: { type: string, minLength: 1 }
|
|
715
|
+
scope: { type: array, minItems: 1, items: { type: string, minLength: 1 } }
|
|
716
|
+
spec_refs:
|
|
717
|
+
type: array
|
|
718
|
+
items:
|
|
719
|
+
type: object
|
|
720
|
+
required: [kind, path]
|
|
721
|
+
additionalProperties: false
|
|
722
|
+
properties:
|
|
723
|
+
kind: { type: string, enum: [discovery, product, architecture, quality, delivery, other] }
|
|
724
|
+
path: { type: string, minLength: 1 }
|
|
725
|
+
evidence:
|
|
726
|
+
type: array
|
|
727
|
+
items:
|
|
728
|
+
type: object
|
|
729
|
+
required: [kind, ref, summary]
|
|
730
|
+
additionalProperties: false
|
|
731
|
+
properties:
|
|
732
|
+
kind: { type: string, enum: [source, docs, runtime, test, deploy, external] }
|
|
733
|
+
ref: { type: string, minLength: 1 }
|
|
734
|
+
summary: { type: string, minLength: 1 }
|
|
735
|
+
verification:
|
|
736
|
+
type: array
|
|
737
|
+
items:
|
|
738
|
+
type: object
|
|
739
|
+
required: [name, command, status, evidence]
|
|
740
|
+
additionalProperties: false
|
|
741
|
+
properties:
|
|
742
|
+
name: { type: string, minLength: 1 }
|
|
743
|
+
command: { type: string, minLength: 1 }
|
|
744
|
+
status: { type: string, enum: [pass, known_red, not_run] }
|
|
745
|
+
evidence: { type: string, minLength: 1 }
|
|
746
|
+
rationale: { type: string, minLength: 1 }
|
|
747
|
+
unknowns:
|
|
748
|
+
type: array
|
|
749
|
+
items:
|
|
750
|
+
type: object
|
|
751
|
+
required: [summary, blocking]
|
|
752
|
+
additionalProperties: false
|
|
753
|
+
properties:
|
|
754
|
+
summary: { type: string, minLength: 1 }
|
|
755
|
+
blocking: { type: boolean }
|
|
756
|
+
owner: { type: string, minLength: 1 }
|
|
757
|
+
provider_refs:
|
|
758
|
+
type: object
|
|
759
|
+
additionalProperties: false
|
|
760
|
+
properties:
|
|
761
|
+
memory:
|
|
762
|
+
type: object
|
|
763
|
+
required: [provider]
|
|
764
|
+
additionalProperties: false
|
|
765
|
+
properties:
|
|
766
|
+
provider: { type: string }
|
|
767
|
+
project: { type: string }
|
|
768
|
+
reference: { type: string }
|
|
769
|
+
revision: { type: string }
|
|
770
|
+
indexed_head: { type: string }
|
|
771
|
+
status: { type: string, enum: [available, unavailable, fresh, stale, unknown] }
|
|
772
|
+
code_graph:
|
|
773
|
+
type: object
|
|
774
|
+
required: [provider]
|
|
775
|
+
additionalProperties: false
|
|
776
|
+
properties:
|
|
777
|
+
provider: { type: string }
|
|
778
|
+
project: { type: string }
|
|
779
|
+
reference: { type: string }
|
|
780
|
+
revision: { type: string }
|
|
781
|
+
indexed_head: { type: string }
|
|
782
|
+
status: { type: string, enum: [available, unavailable, fresh, stale, unknown] }
|
|
783
|
+
output_schema:
|
|
784
|
+
type: object
|
|
785
|
+
required: [baseline]
|
|
786
|
+
additionalProperties: false
|
|
787
|
+
properties:
|
|
788
|
+
baseline: { type: object }
|
|
789
|
+
errors:
|
|
790
|
+
- { code: BASELINE_NOT_FOUND, description: 'baseline id does not exist' }
|
|
791
|
+
- { code: BASELINE_NOT_MUTABLE, description: 'ready and superseded baselines are immutable' }
|
|
792
|
+
- { code: BASELINE_SPEC_MISSING, description: 'a declared specification file does not exist' }
|
|
793
|
+
- { code: PROVIDER_CONTENT_FORBIDDEN, description: 'provider payload content must remain external' }
|
|
794
|
+
cli_subcommand: baseline record
|
|
795
|
+
emits_events: [baseline_recorded]
|
|
796
|
+
|
|
797
|
+
- name: baseline.get
|
|
798
|
+
family: baseline
|
|
799
|
+
description: Read the current or named authoritative baseline with live digest and repository-revision health.
|
|
800
|
+
phase: '11'
|
|
801
|
+
readonly: true
|
|
802
|
+
input_schema:
|
|
803
|
+
type: object
|
|
804
|
+
additionalProperties: false
|
|
805
|
+
properties:
|
|
806
|
+
id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$' }
|
|
807
|
+
output_schema:
|
|
808
|
+
type: object
|
|
809
|
+
required: [baseline, health]
|
|
810
|
+
additionalProperties: false
|
|
811
|
+
properties:
|
|
812
|
+
baseline: { type: object }
|
|
813
|
+
health: { type: object }
|
|
814
|
+
errors:
|
|
815
|
+
- { code: BASELINE_NOT_FOUND, description: 'no matching baseline exists' }
|
|
816
|
+
cli_subcommand: baseline get
|
|
817
|
+
emits_events: []
|
|
818
|
+
|
|
819
|
+
- name: baseline.converge
|
|
820
|
+
family: baseline
|
|
821
|
+
description: Approve a baseline only when its revision, specification digests, evidence, verification, and blocking unknowns satisfy deterministic gates.
|
|
822
|
+
phase: '11'
|
|
823
|
+
writer_role: mcp
|
|
824
|
+
input_schema:
|
|
825
|
+
type: object
|
|
826
|
+
required: [id, expected_revision, approved_by, approval_note]
|
|
827
|
+
additionalProperties: false
|
|
828
|
+
properties:
|
|
829
|
+
id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$' }
|
|
830
|
+
expected_revision: { type: string, minLength: 1 }
|
|
831
|
+
approved_by: { type: string, minLength: 1 }
|
|
832
|
+
approval_note: { type: string, minLength: 3 }
|
|
833
|
+
accept_known_red: { type: boolean, default: false }
|
|
834
|
+
output_schema:
|
|
835
|
+
type: object
|
|
836
|
+
required: [ready, status, blockers, baseline]
|
|
837
|
+
additionalProperties: false
|
|
838
|
+
properties:
|
|
839
|
+
ready: { type: boolean }
|
|
840
|
+
status: { type: string, enum: [blocked, ready] }
|
|
841
|
+
blockers: { type: array, items: { type: string } }
|
|
842
|
+
baseline: { type: object }
|
|
843
|
+
errors:
|
|
844
|
+
- { code: BASELINE_NOT_FOUND, description: 'baseline id does not exist' }
|
|
845
|
+
- { code: BASELINE_NOT_CONVERGEABLE, description: 'baseline lifecycle does not allow convergence' }
|
|
846
|
+
cli_subcommand: baseline converge
|
|
847
|
+
emits_events: [baseline_blocked, baseline_converged]
|
|
848
|
+
|
|
632
849
|
# ────────────────────────── change family ──────────────────────────────
|
|
633
850
|
- name: change.create
|
|
634
851
|
family: change
|
|
@@ -1048,6 +1265,8 @@ tools:
|
|
|
1048
1265
|
errors:
|
|
1049
1266
|
- { code: CHANGE_NOT_READY, description: 'change has not passed convergence' }
|
|
1050
1267
|
- { code: BASELINE_RECONCILIATION_REQUIRED, description: 'baseline update or explicit no-change reason required' }
|
|
1268
|
+
- { code: BASELINE_FILE_MISSING, description: 'a declared baseline update does not exist' }
|
|
1269
|
+
- { code: BASELINE_RECONCILIATION_INCOMPLETE, description: 'repository revision or tracked specification digests remain stale after reconciliation' }
|
|
1051
1270
|
- { code: ARCHIVE_EXISTS, description: 'archive target already exists' }
|
|
1052
1271
|
cli_subcommand: change archive
|
|
1053
1272
|
emits_events: [change_archived]
|
|
@@ -1,47 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://ultra-builder-pro.dev/spec/command-manifest.schema.json",
|
|
4
|
-
"title": "
|
|
5
|
-
"description": "
|
|
4
|
+
"title": "Ultra command launcher frontmatter",
|
|
5
|
+
"description": "Portable source contract for a thin command launcher. Runtime metadata and workflow procedure belong outside the command file.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": ["description"],
|
|
7
|
+
"required": ["description", "workflow-ref"],
|
|
8
8
|
"additionalProperties": false,
|
|
9
9
|
"properties": {
|
|
10
10
|
"description": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"minLength": 10,
|
|
13
|
-
"
|
|
13
|
+
"maxLength": 240,
|
|
14
|
+
"description": "Concise user-visible action description."
|
|
14
15
|
},
|
|
15
16
|
"argument-hint": {
|
|
16
17
|
"oneOf": [
|
|
17
18
|
{ "type": "string" },
|
|
18
19
|
{ "type": "array", "items": { "type": "string" }, "minItems": 1 }
|
|
19
20
|
],
|
|
20
|
-
"description": "
|
|
21
|
-
},
|
|
22
|
-
"allowed-tools": {
|
|
23
|
-
"type": "string",
|
|
24
|
-
"description": "Claude Code convention: comma-separated tool allowlist"
|
|
25
|
-
},
|
|
26
|
-
"model": {
|
|
27
|
-
"type": "string",
|
|
28
|
-
"enum": ["haiku", "sonnet", "opus"],
|
|
29
|
-
"description": "Claude Code convention: model routing hint"
|
|
21
|
+
"description": "Optional host launcher hint; it does not define argument semantics."
|
|
30
22
|
},
|
|
31
23
|
"workflow-ref": {
|
|
32
24
|
"type": "string",
|
|
33
25
|
"pattern": "^@skills/[a-z][a-z0-9\\-]*/SKILL\\.md$",
|
|
34
|
-
"description": "
|
|
35
|
-
},
|
|
36
|
-
"mcp_tools_required": {
|
|
37
|
-
"type": "array",
|
|
38
|
-
"items": { "type": "string", "pattern": "^[a-z]+\\.[a-z_]+$" },
|
|
39
|
-
"uniqueItems": true,
|
|
40
|
-
"description": "Phase 3+: 命令运行时会调用的 MCP tool 名单; 无 MCP 时走 cli_fallback"
|
|
41
|
-
},
|
|
42
|
-
"cli_fallback": {
|
|
43
|
-
"type": "string",
|
|
44
|
-
"description": "Phase 3+: MCP 不可达时回退的 ultra-tools 子命令 (e.g. 'init' -> 'ultra-tools init')"
|
|
26
|
+
"description": "The single Skill that owns this workflow."
|
|
45
27
|
}
|
|
46
28
|
}
|
|
47
29
|
}
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"family": {
|
|
62
62
|
"type": "string",
|
|
63
|
-
"enum": ["task", "memory", "review", "impact", "skill", "session", "ask", "plan", "change", "system"]
|
|
63
|
+
"enum": ["task", "memory", "review", "impact", "skill", "session", "ask", "plan", "baseline", "change", "system"]
|
|
64
64
|
},
|
|
65
65
|
"description": { "type": "string", "minLength": 10 },
|
|
66
66
|
"phase": {
|
|
@@ -1,94 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://ultra-builder-pro.dev/spec/skill-manifest.schema.json",
|
|
4
|
-
"title": "Skill
|
|
5
|
-
"description": "
|
|
4
|
+
"title": "Portable Agent Skill frontmatter",
|
|
5
|
+
"description": "Canonical source contract for skills/*/SKILL.md. Host invocation policy, UI metadata, runtime dependencies, and command hints belong in adapters or host-native metadata, not model instructions.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["name", "description"],
|
|
8
8
|
"additionalProperties": false,
|
|
9
9
|
"properties": {
|
|
10
10
|
"name": {
|
|
11
11
|
"type": "string",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
12
|
+
"minLength": 1,
|
|
13
|
+
"maxLength": 64,
|
|
14
|
+
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
|
|
15
|
+
"description": "Portable Agent Skills name; must match the parent directory."
|
|
14
16
|
},
|
|
15
17
|
"description": {
|
|
16
18
|
"type": "string",
|
|
17
19
|
"minLength": 10,
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"runtime": {
|
|
21
|
-
"oneOf": [
|
|
22
|
-
{ "type": "string", "enum": ["claude", "opencode", "codex", "kimi", "all"] },
|
|
23
|
-
{
|
|
24
|
-
"type": "array",
|
|
25
|
-
"items": { "type": "string", "enum": ["claude", "opencode", "codex", "kimi"] },
|
|
26
|
-
"minItems": 1,
|
|
27
|
-
"uniqueItems": true
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
"description": "v4.5 — which runtime(s) this skill targets. Defaults to 'all' when absent (Phase 4 adapter installs everywhere)."
|
|
31
|
-
},
|
|
32
|
-
"mcp_tools_required": {
|
|
33
|
-
"type": "array",
|
|
34
|
-
"items": { "type": "string", "pattern": "^[a-z]+\\.[a-z_]+$" },
|
|
35
|
-
"uniqueItems": true,
|
|
36
|
-
"description": "v4.5 — MCP tool names this skill calls; Phase 3+ generators verify availability"
|
|
37
|
-
},
|
|
38
|
-
"cli_fallback": {
|
|
39
|
-
"type": "string",
|
|
40
|
-
"description": "v4.5 — ultra-tools subcommand to fall back to when MCP unreachable"
|
|
41
|
-
},
|
|
42
|
-
"complexity_hint": {
|
|
43
|
-
"type": "string",
|
|
44
|
-
"enum": ["haiku", "sonnet", "opus"],
|
|
45
|
-
"description": "v4.5 — model routing hint (Phase 7+)"
|
|
46
|
-
},
|
|
47
|
-
"argument-hint": {
|
|
48
|
-
"type": "string",
|
|
49
|
-
"description": "Claude Code convention: hint shown after slash-command name"
|
|
50
|
-
},
|
|
51
|
-
"allowed-tools": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"description": "Claude Code convention: comma-separated tool allowlist"
|
|
54
|
-
},
|
|
55
|
-
"user-invocable": {
|
|
56
|
-
"type": "boolean",
|
|
57
|
-
"description": "Claude Code convention: can the user call this via slash command"
|
|
58
|
-
},
|
|
59
|
-
"disable-model-invocation": {
|
|
60
|
-
"type": "boolean",
|
|
61
|
-
"description": "Claude Code convention: skill is not auto-invoked by the model"
|
|
62
|
-
},
|
|
63
|
-
"context": {
|
|
64
|
-
"type": "string",
|
|
65
|
-
"enum": ["fork", "main"],
|
|
66
|
-
"description": "Claude Code convention: 'fork' isolates skill output from main conversation"
|
|
67
|
-
},
|
|
68
|
-
"license": {
|
|
69
|
-
"type": "string",
|
|
70
|
-
"description": "third-party skill license (e.g. MIT)"
|
|
71
|
-
},
|
|
72
|
-
"metadata": {
|
|
73
|
-
"type": "object",
|
|
74
|
-
"additionalProperties": true,
|
|
75
|
-
"properties": {
|
|
76
|
-
"author": { "type": "string" },
|
|
77
|
-
"version": { "type": "string" }
|
|
78
|
-
},
|
|
79
|
-
"description": "third-party metadata block (vercel skills, etc.)"
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
"allOf": [
|
|
83
|
-
{
|
|
84
|
-
"if": { "required": ["user-invocable"], "properties": { "user-invocable": { "const": true } } },
|
|
85
|
-
"then": {
|
|
86
|
-
"not": {
|
|
87
|
-
"required": ["disable-model-invocation"],
|
|
88
|
-
"properties": { "disable-model-invocation": { "const": true } }
|
|
89
|
-
},
|
|
90
|
-
"errorMessage": "user-invocable=true cannot coexist with disable-model-invocation=true"
|
|
91
|
-
}
|
|
20
|
+
"maxLength": 1024,
|
|
21
|
+
"description": "Concise discovery metadata that states both what the skill does and when to use it."
|
|
92
22
|
}
|
|
93
|
-
|
|
23
|
+
}
|
|
94
24
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
-- Ultra Builder Pro — authoritative state schema
|
|
2
2
|
-- Phase 2 builds .ultra/state.db from this file. Source of truth for all
|
|
3
|
-
-- task / session / event / telemetry data. tasks.json and context md status
|
|
3
|
+
-- baseline / change / task / session / event / telemetry data. tasks.json and context md status
|
|
4
4
|
-- header are projections (PLAN §7.1, D18, D32).
|
|
5
5
|
--
|
|
6
|
-
-- Trace: docs/PLAN.zh-CN.md §7.1; decisions D18/D30/D31/D32/D37.
|
|
6
|
+
-- Trace: docs/PLAN.zh-CN.md §7.1; decisions D18/D30/D31/D32/D37/D52/D54.
|
|
7
7
|
--
|
|
8
8
|
-- PRAGMAs are applied by mcp-server/lib/state-db.ts on connection open;
|
|
9
9
|
-- they cannot be persisted in CREATE statements but are documented here.
|
|
@@ -12,6 +12,35 @@
|
|
|
12
12
|
-- PRAGMA busy_timeout=5000; -- block up to 5s on lock (R25)
|
|
13
13
|
-- PRAGMA foreign_keys=ON; -- enforce FK constraints
|
|
14
14
|
|
|
15
|
+
-- ──────────────────────────── project baseline ─────────────────────────────
|
|
16
|
+
-- The baseline is the approved, repository-scoped snapshot that every change
|
|
17
|
+
-- is measured against. It stores digests and evidence references, never source,
|
|
18
|
+
-- prompt, transcript, memory, or code-graph payloads.
|
|
19
|
+
CREATE TABLE IF NOT EXISTS baselines (
|
|
20
|
+
id TEXT PRIMARY KEY,
|
|
21
|
+
project_name TEXT NOT NULL,
|
|
22
|
+
project_type TEXT,
|
|
23
|
+
stack TEXT,
|
|
24
|
+
mode TEXT NOT NULL CHECK (mode IN ('greenfield', 'brownfield', 'migrated')),
|
|
25
|
+
status TEXT NOT NULL DEFAULT 'draft'
|
|
26
|
+
CHECK (status IN ('draft', 'adopting', 'blocked', 'ready', 'superseded')),
|
|
27
|
+
repository_root TEXT NOT NULL DEFAULT '.',
|
|
28
|
+
scope_json TEXT NOT NULL DEFAULT '["."]',
|
|
29
|
+
repository_revision TEXT,
|
|
30
|
+
spec_refs_json TEXT NOT NULL DEFAULT '[]',
|
|
31
|
+
evidence_json TEXT NOT NULL DEFAULT '[]',
|
|
32
|
+
verification_json TEXT NOT NULL DEFAULT '[]',
|
|
33
|
+
unknowns_json TEXT NOT NULL DEFAULT '[]',
|
|
34
|
+
provider_refs_json TEXT NOT NULL DEFAULT '{}',
|
|
35
|
+
approved_by TEXT,
|
|
36
|
+
approval_note TEXT,
|
|
37
|
+
started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
38
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
39
|
+
converged_at TEXT
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE INDEX IF NOT EXISTS baselines_status ON baselines(status, updated_at);
|
|
43
|
+
|
|
15
44
|
-- ──────────────────────────── changes ─────────────────────────────────────
|
|
16
45
|
-- A project baseline is continuous; each feature, fix, incident, or redesign
|
|
17
46
|
-- is an independently converged change unit. Only changes become terminal.
|
|
@@ -305,3 +334,5 @@ INSERT OR IGNORE INTO schema_version (version, description)
|
|
|
305
334
|
VALUES ('9.1', 'Kimi runtime support in durable events and sessions');
|
|
306
335
|
INSERT OR IGNORE INTO schema_version (version, description)
|
|
307
336
|
VALUES ('10.0', 'Role-scoped context snapshots, deterministic breadcrumbs, and approval-gated specification learning');
|
|
337
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
338
|
+
VALUES ('11.0', 'Greenfield and brownfield baseline adoption, convergence, and drift authority');
|
|
@@ -10,6 +10,7 @@ const fs = require('node:fs');
|
|
|
10
10
|
const path = require('node:path');
|
|
11
11
|
|
|
12
12
|
const ops = require('../../mcp-server/lib/state-ops.cjs');
|
|
13
|
+
const baselines = require('../../mcp-server/lib/baseline-workflow.cjs');
|
|
13
14
|
|
|
14
15
|
const USAGE = `ultra-tools status [flags]
|
|
15
16
|
|
|
@@ -64,12 +65,23 @@ function parseFlags(args) {
|
|
|
64
65
|
return out;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function buildCostPanel(db, { since = null, limit = 3 } = {}) {
|
|
68
|
+
function buildCostPanel(db, { since = null, limit = 3, rootDir = process.cwd() } = {}) {
|
|
68
69
|
const by_runtime = ops.aggregateTelemetryByRuntime(db, { since });
|
|
69
70
|
const top_tasks = ops.aggregateTelemetryByTask(db, { since, limit });
|
|
70
71
|
const total_cost_usd = by_runtime.reduce((acc, r) => acc + (r.cost_usd || 0), 0);
|
|
72
|
+
const baselineHealth = baselines.inspectBaseline(db, { rootDir });
|
|
73
|
+
const current = baselineHealth.baseline;
|
|
71
74
|
return {
|
|
72
75
|
period: { since: since || 'all-time' },
|
|
76
|
+
baseline: {
|
|
77
|
+
id: current?.id || null,
|
|
78
|
+
mode: current?.mode || null,
|
|
79
|
+
status: current?.status || 'missing',
|
|
80
|
+
health: baselineHealth.status,
|
|
81
|
+
repository_revision: current?.repository_revision || null,
|
|
82
|
+
blockers: baselineHealth.blockers,
|
|
83
|
+
warnings: baselineHealth.warnings,
|
|
84
|
+
},
|
|
73
85
|
by_runtime,
|
|
74
86
|
top_tasks,
|
|
75
87
|
total_cost_usd,
|
|
@@ -84,6 +96,11 @@ function formatCost(n) {
|
|
|
84
96
|
|
|
85
97
|
function renderHuman(panel) {
|
|
86
98
|
const lines = [];
|
|
99
|
+
const baseline = panel.baseline;
|
|
100
|
+
lines.push(
|
|
101
|
+
`Baseline: ${baseline.mode || 'none'}/${baseline.status} · ${baseline.health === 'pass' ? 'ready' : 'blocked'}`,
|
|
102
|
+
);
|
|
103
|
+
if (baseline.blockers.length > 0) lines.push(`Baseline blockers: ${baseline.blockers.join(', ')}`);
|
|
87
104
|
lines.push(`Period: ${panel.period.since}`);
|
|
88
105
|
lines.push(`Total cost: ${formatCost(panel.total_cost_usd)}`);
|
|
89
106
|
lines.push('');
|
|
@@ -136,7 +153,8 @@ function dispatch(args) {
|
|
|
136
153
|
const Database = require('better-sqlite3');
|
|
137
154
|
const db = new Database(dbPath, { readonly: true });
|
|
138
155
|
try {
|
|
139
|
-
const
|
|
156
|
+
const rootDir = path.dirname(path.dirname(dbPath));
|
|
157
|
+
const panel = buildCostPanel(db, { since, limit: flags.limit, rootDir });
|
|
140
158
|
if (flags.json) {
|
|
141
159
|
emit({ ok: true, data: panel });
|
|
142
160
|
} else {
|
|
@@ -9,13 +9,14 @@ const { initProject, InitProjectError } = require('../../mcp-server/lib/init-pro
|
|
|
9
9
|
const USAGE = `ultra-tools task <verb> [flags]
|
|
10
10
|
|
|
11
11
|
VERBS:
|
|
12
|
-
init-project
|
|
12
|
+
init-project Initialize or adopt a project with authoritative Ultra state
|
|
13
13
|
|
|
14
14
|
FLAGS (init-project):
|
|
15
15
|
--target-dir <path> target project root (default: cwd)
|
|
16
16
|
--project-name <name> project name (required)
|
|
17
17
|
--project-type <type> web | api | cli | fullstack | other
|
|
18
18
|
--stack <stack> tech stack descriptor (comma-separated ok)
|
|
19
|
+
--mode <mode> auto | greenfield | brownfield (default: auto)
|
|
19
20
|
--overwrite replace existing .ultra/ (backup created)
|
|
20
21
|
--source-template <path> override bundled template source
|
|
21
22
|
-h, --help show this message
|
|
@@ -34,6 +35,7 @@ function parseInitFlags(args) {
|
|
|
34
35
|
case '--project-name': flags.project_name = args[++i]; break;
|
|
35
36
|
case '--project-type': flags.project_type = args[++i]; break;
|
|
36
37
|
case '--stack': flags.stack = args[++i]; break;
|
|
38
|
+
case '--mode': flags.mode = args[++i]; break;
|
|
37
39
|
case '--source-template': flags.source_template = args[++i]; break;
|
|
38
40
|
case '--overwrite': flags.overwrite = true; break;
|
|
39
41
|
case '--no-overwrite': flags.overwrite = false; break;
|
|
@@ -59,6 +61,7 @@ function dispatchInitProject(rawArgs) {
|
|
|
59
61
|
project_name: flags.project_name,
|
|
60
62
|
project_type: flags.project_type,
|
|
61
63
|
stack: flags.stack,
|
|
64
|
+
mode: flags.mode || 'auto',
|
|
62
65
|
overwrite: !!flags.overwrite,
|
|
63
66
|
source_template: flags.source_template,
|
|
64
67
|
};
|
|
@@ -63,6 +63,26 @@ test('buildCostPanel: empty db → zero totals, empty arrays', () => {
|
|
|
63
63
|
assert.equal(out.total_cost_usd, 0);
|
|
64
64
|
assert.equal(out.by_runtime.length, 0);
|
|
65
65
|
assert.equal(out.top_tasks.length, 0);
|
|
66
|
+
assert.deepEqual(out.baseline, {
|
|
67
|
+
id: null, mode: null, status: 'missing', health: 'fail',
|
|
68
|
+
repository_revision: null, blockers: ['BASELINE_MISSING'], warnings: [],
|
|
69
|
+
});
|
|
70
|
+
} finally { teardown(dir, db); }
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('status exposes an in-progress brownfield baseline from authoritative state', () => {
|
|
74
|
+
const { dir, db } = freshFixture();
|
|
75
|
+
try {
|
|
76
|
+
db.prepare(
|
|
77
|
+
`INSERT INTO baselines (id, project_name, mode, status)
|
|
78
|
+
VALUES ('adoption', 'legacy', 'brownfield', 'adopting')`,
|
|
79
|
+
).run();
|
|
80
|
+
const out = statusCmd.buildCostPanel(db, { rootDir: dir });
|
|
81
|
+
assert.equal(out.baseline.id, 'adoption');
|
|
82
|
+
assert.equal(out.baseline.mode, 'brownfield');
|
|
83
|
+
assert.equal(out.baseline.status, 'adopting');
|
|
84
|
+
assert.deepEqual(out.baseline.blockers, ['BASELINE_NOT_READY:adopting']);
|
|
85
|
+
assert.match(statusCmd.renderHuman(out), /Baseline: brownfield\/adopting.*blocked/i);
|
|
66
86
|
} finally { teardown(dir, db); }
|
|
67
87
|
});
|
|
68
88
|
|
|
@@ -14,6 +14,11 @@ const CLI = path.join(__dirname, 'cli.cjs');
|
|
|
14
14
|
function fixture() {
|
|
15
15
|
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-system-cli-'));
|
|
16
16
|
const { db } = initStateDb(path.join(rootDir, '.ultra', 'state.db'));
|
|
17
|
+
db.prepare(
|
|
18
|
+
`INSERT INTO baselines
|
|
19
|
+
(id, project_name, mode, status, approved_by, approval_note, converged_at)
|
|
20
|
+
VALUES ('test-baseline', 'fixture', 'migrated', 'ready', 'test', 'legacy fixture', ?)`,
|
|
21
|
+
).run(new Date().toISOString());
|
|
17
22
|
closeStateDb(db);
|
|
18
23
|
return rootDir;
|
|
19
24
|
}
|