ultra-builder-pro-cli 0.21.1 → 0.22.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.
Files changed (47) hide show
  1. package/.ultra-template/tasks/tasks.json +10 -3
  2. package/.ultra-template/templates/task-context.md +19 -0
  3. package/CHANGELOG.md +40 -0
  4. package/README.md +166 -22
  5. package/adapters/opencode.js +23 -12
  6. package/docs/AGENT-CONTEXT.md +22 -13
  7. package/docs/ARCHITECTURE.md +59 -24
  8. package/docs/ARTIFACT-AUTHORITY.md +70 -30
  9. package/docs/COMMIT-HASH-BACKFILL.md +33 -90
  10. package/docs/DECISIONS.md +9 -7
  11. package/docs/LEGACY-CLI-CROSSWALK.md +10 -2
  12. package/docs/PLUGIN-ISOLATION-CONTRACT.md +3 -2
  13. package/docs/ROADMAP.md +3 -3
  14. package/docs/RUNTIME-COMPAT-MATRIX.md +8 -6
  15. package/docs/STATE-DB-ACCESS-POLICY.md +35 -7
  16. package/docs/WORKFLOW-LIFECYCLE.md +40 -16
  17. package/hooks/README.md +5 -4
  18. package/hooks/active_task_context.py +41 -39
  19. package/mcp-server/lib/artifact-registry.cjs +7 -6
  20. package/mcp-server/lib/baseline-workflow.cjs +60 -24
  21. package/mcp-server/lib/context-paths.cjs +34 -3
  22. package/mcp-server/lib/doctor.cjs +28 -0
  23. package/mcp-server/lib/git-bootstrap.cjs +0 -1
  24. package/mcp-server/lib/init-project.cjs +52 -2
  25. package/mcp-server/lib/projector.cjs +43 -8
  26. package/mcp-server/lib/state-authority.cjs +19 -3
  27. package/mcp-server/lib/state-ops.cjs +6 -1
  28. package/mcp-server/lib/task-ledger.cjs +1342 -0
  29. package/mcp-server/server.cjs +145 -9
  30. package/package.json +1 -1
  31. package/skills/ultra-change/SKILL.md +10 -2
  32. package/skills/ultra-deliver/SKILL.md +6 -3
  33. package/skills/ultra-dev/SKILL.md +21 -6
  34. package/skills/ultra-doctor/SKILL.md +10 -1
  35. package/skills/ultra-init/SKILL.md +18 -9
  36. package/skills/ultra-plan/SKILL.md +11 -4
  37. package/skills/ultra-research/SKILL.md +12 -13
  38. package/skills/ultra-review/SKILL.md +5 -3
  39. package/skills/ultra-status/SKILL.md +11 -7
  40. package/skills/ultra-test/SKILL.md +3 -2
  41. package/spec/cli-protocol.md +3 -0
  42. package/spec/mcp-tools.yaml +127 -0
  43. package/spec/schemas/context-file.v4.5.schema.json +1 -1
  44. package/spec/schemas/state-db.sql +1 -1
  45. package/spec/schemas/task-ledger.v1.schema.json +217 -0
  46. package/ultra-tools/commands/migrate.cjs +5 -2
  47. package/.ultra-template/tasks/contexts/TEMPLATE.md +0 -19
@@ -233,6 +233,106 @@ tools:
233
233
  emits_events: []
234
234
  trace_to: '§7.3'
235
235
 
236
+ - name: task.ledger_get
237
+ family: task
238
+ description: Read the Git-facing durable baseline, Change, and task checkpoint ledger and compare it with local SQLite authority.
239
+ phase: '21'
240
+ readonly: true
241
+ writer_role: any
242
+ input_schema:
243
+ type: object
244
+ additionalProperties: false
245
+ output_schema:
246
+ type: object
247
+ required: [ledger, health]
248
+ additionalProperties: false
249
+ properties:
250
+ ledger: { type: ['object', 'null'] }
251
+ health: { type: object }
252
+ errors:
253
+ - { code: TASK_LEDGER_INVALID, description: 'the Git ledger is malformed' }
254
+ - { code: TASK_LEDGER_DIGEST_MISMATCH, description: 'ledger content does not match its digest' }
255
+ - { code: TASK_LEDGER_UNSAFE, description: 'ledger path is a symlink or non-regular file' }
256
+ cli_subcommand: task ledger-get
257
+ emits_events: []
258
+ trace_to: 'docs/ARTIFACT-AUTHORITY.md#team-task-ledger'
259
+
260
+ - name: task.ledger_publish
261
+ family: task
262
+ description: Publish a low-frequency Git-facing baseline, Change, and task checkpoint from local SQLite authority.
263
+ phase: '21'
264
+ writer_role: mcp
265
+ input_schema:
266
+ type: object
267
+ additionalProperties: false
268
+ properties:
269
+ reason:
270
+ type: string
271
+ minLength: 1
272
+ default: manual_checkpoint
273
+ output_schema:
274
+ type: object
275
+ required: [changed, path, generation, state_digest]
276
+ additionalProperties: false
277
+ properties:
278
+ changed: { type: boolean }
279
+ path: { type: string }
280
+ generation: { type: integer, minimum: 0 }
281
+ state_digest: { type: string, pattern: '^[0-9a-f]{64}$' }
282
+ migrated_legacy_projection: { type: boolean }
283
+ legacy_backup_path: { type: string }
284
+ errors:
285
+ - { code: TASK_LEDGER_INVALID, description: 'the prior Git ledger is malformed' }
286
+ - { code: TASK_LEDGER_DIGEST_MISMATCH, description: 'prior ledger content does not match its digest' }
287
+ - { code: TASK_LEDGER_UNSAFE, description: 'ledger path is a symlink or non-regular file' }
288
+ - { code: TASK_LEDGER_CHANGE_MISSING, description: 'a task has no portable owning Change' }
289
+ - { code: TASK_LEDGER_LEGACY_CONFLICT, description: 'the legacy task projection differs from SQLite authority and cannot be replaced automatically' }
290
+ - { code: TASK_LEDGER_REVALIDATION_REQUIRED, description: 'an imported ready baseline must converge in this checkout before publication' }
291
+ cli_subcommand: task ledger-publish
292
+ emits_events: [task_ledger_published]
293
+ trace_to: 'docs/ARTIFACT-AUTHORITY.md#team-task-ledger'
294
+
295
+ - name: task.ledger_import
296
+ family: task
297
+ description: Import a validated Git checkpoint into local SQLite authority with per-baseline, per-Change, and per-task conflict checks.
298
+ phase: '21'
299
+ writer_role: mcp
300
+ input_schema:
301
+ type: object
302
+ additionalProperties: false
303
+ output_schema:
304
+ type: object
305
+ required: [imported, preserved, deleted, imported_changes, preserved_changes, imported_baseline, preserved_baseline, generation, state_digest, requires_plan_revalidation, requires_baseline_revalidation, already_current]
306
+ additionalProperties: false
307
+ properties:
308
+ imported: { type: integer, minimum: 0 }
309
+ preserved: { type: integer, minimum: 0 }
310
+ deleted: { type: integer, minimum: 0 }
311
+ imported_changes: { type: integer, minimum: 0 }
312
+ preserved_changes: { type: integer, minimum: 0 }
313
+ imported_baseline: { type: boolean }
314
+ preserved_baseline: { type: boolean }
315
+ generation: { type: integer, minimum: 0 }
316
+ state_digest: { type: string, pattern: '^[0-9a-f]{64}$' }
317
+ requires_plan_revalidation: { type: boolean }
318
+ requires_baseline_revalidation: { type: boolean }
319
+ already_current: { type: boolean }
320
+ errors:
321
+ - { code: TASK_LEDGER_INVALID, description: 'the Git ledger is malformed' }
322
+ - { code: TASK_LEDGER_DIGEST_MISMATCH, description: 'ledger content does not match its digest' }
323
+ - { code: TASK_LEDGER_UNSAFE, description: 'ledger path is a symlink or non-regular file' }
324
+ - { code: TASK_LEDGER_CONFLICT, description: 'the same task changed locally and in Git' }
325
+ - { code: TASK_LEDGER_ACTIVE_TASK_CONFLICT, description: 'Git changed a task with an active local session' }
326
+ - { code: TASK_LEDGER_STALE, description: 'the Git ledger is older than the last local checkpoint' }
327
+ - { code: TASK_LEDGER_HISTORY_CONFLICT, description: 'the Git ledger does not descend from the last local checkpoint' }
328
+ - { code: TASK_LEDGER_CHANGE_MISSING, description: 'a task references an unavailable Change' }
329
+ - { code: TASK_LEDGER_PARENT_MISSING, description: 'a task references an unavailable parent task' }
330
+ - { code: TASK_LEDGER_CHANGE_CONFLICT, description: 'the same Change changed locally and in Git' }
331
+ - { code: TASK_LEDGER_BASELINE_CONFLICT, description: 'the same baseline changed locally and in Git' }
332
+ cli_subcommand: task ledger-import
333
+ emits_events: [task_ledger_imported]
334
+ trace_to: 'docs/ARTIFACT-AUTHORITY.md#team-task-ledger'
335
+
236
336
  - name: task.switch_tag
237
337
  family: task
238
338
  description: Change a task's tag (branch-scoped context partition, Phase 7.2). Emits task_tag_changed.
@@ -389,6 +489,32 @@ tools:
389
489
  migration_backup_path:
390
490
  type: string
391
491
  description: pre-migration database backup created while resuming an older schema
492
+ runtime_migration_backup_path:
493
+ type: string
494
+ description: verified backup of a legacy runtime layout moved into `.ultra/.runtime/`
495
+ team_checkpoint:
496
+ type: object
497
+ additionalProperties: false
498
+ required: [generation, state_digest, imported_tasks, deleted_tasks, imported_changes, imported_baseline, requires_plan_revalidation, requires_baseline_revalidation, already_current]
499
+ properties:
500
+ generation: { type: integer, minimum: 0 }
501
+ state_digest: { type: string, pattern: '^[0-9a-f]{64}$' }
502
+ imported_tasks: { type: integer, minimum: 0 }
503
+ deleted_tasks: { type: integer, minimum: 0 }
504
+ imported_changes: { type: integer, minimum: 0 }
505
+ imported_baseline: { type: boolean }
506
+ requires_plan_revalidation: { type: boolean }
507
+ requires_baseline_revalidation: { type: boolean }
508
+ already_current: { type: boolean }
509
+ published:
510
+ type: boolean
511
+ description: true when resume replaced a matching legacy task projection with a new team checkpoint
512
+ migrated_legacy_projection:
513
+ type: boolean
514
+ description: true when the prior tracked file used the supported legacy projection format
515
+ legacy_backup_path:
516
+ type: string
517
+ description: exact-byte backup of the replaced legacy task projection
392
518
  errors:
393
519
  - { code: ULTRA_DIR_EXISTS, description: '.ultra/ already exists and overwrite=false' }
394
520
  - { code: TEMPLATE_MISSING, description: 'source_template path does not exist' }
@@ -397,6 +523,7 @@ tools:
397
523
  - { code: LEGACY_STATE_MIGRATION_REQUIRED, description: 'projection-only tasks must be imported before resume' }
398
524
  - { code: STATE_AUTHORITY_CONFLICT, description: 'projection tasks and authoritative state cannot be reconciled automatically' }
399
525
  - { code: STATE_PROJECTION_INVALID, description: 'the existing task projection is malformed' }
526
+ - { code: TASK_LEDGER_LEGACY_CONFLICT, description: 'the legacy task projection differs from SQLite authority and cannot be upgraded automatically' }
400
527
  - { code: GIT_INIT_FAILED, description: 'the local Git repository or Ultra ignore rule could not be initialized' }
401
528
  - { code: GITIGNORE_UNSAFE, description: 'root .gitignore is a symlink or non-file and cannot be updated safely' }
402
529
  - { code: GITIGNORE_INEFFECTIVE, description: 'the effective Git rules still expose the `.ultra` authority' }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://ultra-builder-pro.dev/spec/context-file.v4.5.schema.json",
4
4
  "title": "context-file projection (v4.5)",
5
- "description": "Schema for the parsed representation of .ultra/tasks/contexts/task-*.md. The header is regenerated by the projector from state.db. Body sections are author-owned; status MUST NOT appear in body. Authority boundary: docs/DECISIONS.md.",
5
+ "description": "Schema for the parsed representation of .ultra/.runtime/projections/contexts/task-*.md. The file is regenerated by the projector from state.db and remains checkout-local. Authority boundary: docs/ARTIFACT-AUTHORITY.md.",
6
6
  "type": "object",
7
7
  "required": ["header", "body"],
8
8
  "additionalProperties": false,
@@ -105,7 +105,7 @@ CREATE TABLE IF NOT EXISTS tasks (
105
105
  docs_impact_json TEXT NOT NULL DEFAULT '{"status":"unknown","files":[],"rationale":null}',
106
106
  ownership_json TEXT NOT NULL DEFAULT '{}',
107
107
  context_file TEXT, -- projection target path
108
- completion_commit TEXT, -- backfilled hash (Phase 2.8)
108
+ completion_commit TEXT, -- checkout-local integrated commit evidence
109
109
  change_id TEXT REFERENCES changes(id) ON DELETE SET NULL,
110
110
  parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL, -- Phase 8A.1: task.expand subtask→parent
111
111
  created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
@@ -0,0 +1,217 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ultra-builder-pro.dev/spec/task-ledger.v1.schema.json",
4
+ "title": "Ultra team task ledger v1",
5
+ "description": "Git-facing checkpoint ledger for durable task contracts and statuses. Live sessions, leases, worktrees, and in-progress ownership remain in .ultra/.runtime/state.db.",
6
+ "type": "object",
7
+ "required": [
8
+ "kind",
9
+ "schema_version",
10
+ "generation",
11
+ "parent_digest",
12
+ "ancestors",
13
+ "state_digest",
14
+ "published_at",
15
+ "reason",
16
+ "baseline",
17
+ "changes",
18
+ "tasks"
19
+ ],
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "kind": { "const": "ultra-team-task-ledger" },
23
+ "schema_version": { "const": "1.0" },
24
+ "generation": { "type": "integer", "minimum": 0 },
25
+ "parent_digest": {
26
+ "type": ["string", "null"],
27
+ "pattern": "^[0-9a-f]{64}$"
28
+ },
29
+ "ancestors": {
30
+ "type": "array",
31
+ "maxItems": 64,
32
+ "items": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
33
+ },
34
+ "state_digest": {
35
+ "type": "string",
36
+ "pattern": "^[0-9a-f]{64}$"
37
+ },
38
+ "published_at": {
39
+ "type": ["string", "null"],
40
+ "format": "date-time"
41
+ },
42
+ "reason": { "type": "string", "minLength": 1 },
43
+ "baseline": {
44
+ "oneOf": [
45
+ { "type": "null" },
46
+ { "$ref": "#/$defs/baseline" }
47
+ ]
48
+ },
49
+ "changes": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "object",
53
+ "required": [
54
+ "id",
55
+ "title",
56
+ "kind",
57
+ "status",
58
+ "intent",
59
+ "artifact_root",
60
+ "revision",
61
+ "parent_digest",
62
+ "digest"
63
+ ],
64
+ "additionalProperties": false,
65
+ "properties": {
66
+ "id": { "type": "string" },
67
+ "title": { "type": "string", "minLength": 1 },
68
+ "kind": { "type": "string", "enum": ["quick", "standard", "major", "incident"] },
69
+ "status": { "type": "string", "enum": ["active", "blocked", "ready", "archived", "cancelled"] },
70
+ "intent": { "type": "string", "minLength": 1 },
71
+ "docs_impact": { "type": "object" },
72
+ "provider_refs": { "type": "object" },
73
+ "baseline_bypass": { "type": "object" },
74
+ "contract": { "type": "object" },
75
+ "classification": { "type": "object" },
76
+ "research_disposition": { "type": "object" },
77
+ "base_commit": { "type": "string" },
78
+ "artifact_root": { "type": "string", "minLength": 1 },
79
+ "closed_at": { "type": "string" },
80
+ "revision": { "type": "integer", "minimum": 1 },
81
+ "parent_digest": {
82
+ "type": ["string", "null"],
83
+ "pattern": "^[0-9a-f]{64}$"
84
+ },
85
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
86
+ }
87
+ }
88
+ },
89
+ "tasks": {
90
+ "type": "array",
91
+ "items": { "$ref": "#/$defs/task" }
92
+ }
93
+ },
94
+ "$defs": {
95
+ "baseline": {
96
+ "type": "object",
97
+ "required": [
98
+ "id",
99
+ "project_name",
100
+ "mode",
101
+ "status",
102
+ "scope",
103
+ "worktree_accepted",
104
+ "known_red_accepted",
105
+ "spec_refs",
106
+ "evidence",
107
+ "verification",
108
+ "unknowns",
109
+ "gaps",
110
+ "classification",
111
+ "provider_refs",
112
+ "revision",
113
+ "parent_digest",
114
+ "digest"
115
+ ],
116
+ "additionalProperties": false,
117
+ "properties": {
118
+ "id": { "type": "string", "minLength": 1 },
119
+ "project_name": { "type": "string", "minLength": 1 },
120
+ "project_type": { "type": "string" },
121
+ "stack": { "type": "string" },
122
+ "mode": {
123
+ "type": "string",
124
+ "enum": ["greenfield", "brownfield", "migrated"]
125
+ },
126
+ "status": {
127
+ "type": "string",
128
+ "enum": ["draft", "adopting", "blocked", "ready"]
129
+ },
130
+ "scope": {
131
+ "type": "array",
132
+ "minItems": 1,
133
+ "items": { "type": "string", "minLength": 1 }
134
+ },
135
+ "repository_revision": { "type": "string" },
136
+ "repository_branch": { "type": "string" },
137
+ "worktree_state": { "type": "string" },
138
+ "worktree_digest": { "type": "string" },
139
+ "worktree_accepted": { "type": "boolean" },
140
+ "known_red_accepted": { "type": "boolean" },
141
+ "spec_refs": { "type": "array" },
142
+ "evidence": { "type": "array" },
143
+ "verification": { "type": "array" },
144
+ "unknowns": { "type": "array" },
145
+ "gaps": { "type": "array" },
146
+ "classification": { "type": "object" },
147
+ "provider_refs": { "type": "object" },
148
+ "research_run_id": { "type": "string" },
149
+ "approved_by": { "type": "string" },
150
+ "approval_note": { "type": "string" },
151
+ "converged_at": { "type": "string" },
152
+ "revision": { "type": "integer", "minimum": 1 },
153
+ "parent_digest": {
154
+ "type": ["string", "null"],
155
+ "pattern": "^[0-9a-f]{64}$"
156
+ },
157
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
158
+ }
159
+ },
160
+ "task": {
161
+ "type": "object",
162
+ "required": [
163
+ "id",
164
+ "title",
165
+ "type",
166
+ "priority",
167
+ "status",
168
+ "deps",
169
+ "files_modified",
170
+ "stale",
171
+ "acceptance",
172
+ "context_refs",
173
+ "docs_impact",
174
+ "ownership",
175
+ "revision",
176
+ "parent_digest",
177
+ "digest"
178
+ ],
179
+ "additionalProperties": false,
180
+ "properties": {
181
+ "id": { "type": "string", "pattern": "^[a-zA-Z0-9_\\-]+$" },
182
+ "title": { "type": "string", "minLength": 3 },
183
+ "type": { "type": "string", "enum": ["architecture", "feature", "bugfix"] },
184
+ "priority": { "type": "string", "enum": ["P0", "P1", "P2", "P3"] },
185
+ "complexity": { "type": "integer", "minimum": 1, "maximum": 10 },
186
+ "estimated_days": { "type": "number", "exclusiveMinimum": 0 },
187
+ "status": {
188
+ "type": "string",
189
+ "enum": ["pending", "completed", "blocked", "expanded"]
190
+ },
191
+ "deps": { "type": "array", "items": { "type": "string" } },
192
+ "files_modified": { "type": "array", "items": { "type": "string" } },
193
+ "stale": { "type": "boolean" },
194
+ "trace_to": { "type": "string" },
195
+ "outcome": { "type": "string" },
196
+ "slice_kind": {
197
+ "type": "string",
198
+ "enum": ["tracer_bullet", "expand_contract", "integration_checkpoint"]
199
+ },
200
+ "public_seam": { "type": "string" },
201
+ "verification_command": { "type": "string" },
202
+ "acceptance": { "type": "array", "items": { "type": "object" } },
203
+ "context_refs": { "type": "array", "items": { "type": "object" } },
204
+ "docs_impact": { "type": "object" },
205
+ "ownership": { "type": "object" },
206
+ "change_id": { "type": "string" },
207
+ "parent_id": { "type": "string" },
208
+ "revision": { "type": "integer", "minimum": 1 },
209
+ "parent_digest": {
210
+ "type": ["string", "null"],
211
+ "pattern": "^[0-9a-f]{64}$"
212
+ },
213
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
214
+ }
215
+ }
216
+ }
217
+ }
@@ -246,8 +246,11 @@ function sanitizeLegacyContextTemplate(sourceDir) {
246
246
  /Read by mid_workflow_recall\.py and session_context\.py and injected into agent context\./g,
247
247
  'Used as task-local acceptance criteria by the active Ultra workflow.',
248
248
  );
249
- if (next === current) return false;
250
- fs.writeFileSync(file, next);
249
+ const target = path.join(sourceDir, '.ultra', 'templates', 'task-context.md');
250
+ if (fs.existsSync(target)) return false;
251
+ fs.mkdirSync(path.dirname(target), { recursive: true });
252
+ fs.writeFileSync(target, next);
253
+ fs.rmSync(file);
251
254
  return true;
252
255
  }
253
256
 
@@ -1,19 +0,0 @@
1
- <!-- The projector owns YAML frontmatter and the generated execution contract. -->
2
-
3
- # Task Notes
4
-
5
- Use this body only for task-specific implementation discoveries that are not already
6
- authoritative task fields. Stable specification learning must follow the change
7
- approval workflow.
8
-
9
- ## Implementation Notes
10
-
11
- - [Evidence-backed note with a source reference]
12
-
13
- ## Open Questions
14
-
15
- - [Question, consequence, owner, and next evidence]
16
-
17
- ## Recovery Notes
18
-
19
- - [Current safe resume point and any external prerequisite]