ultra-builder-pro-cli 0.13.0 → 0.15.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/.ultra-template/docs/research/README.md +11 -7
- package/.ultra-template/specs/architecture.md +36 -36
- package/.ultra-template/specs/discovery.md +46 -33
- package/.ultra-template/specs/product.md +38 -29
- package/.ultra-template/specs/research-distillate.md +48 -0
- package/.ultra-template/tasks/contexts/TEMPLATE.md +11 -28
- package/CHANGELOG.md +86 -1
- package/README.md +40 -26
- package/adapters/_shared/codex-assets.cjs +29 -165
- package/adapters/_shared/file-ops.cjs +6 -2
- package/adapters/_shared/runtime-assets.cjs +1 -0
- package/adapters/claude.js +3 -2
- package/adapters/codex.js +1 -0
- package/adapters/kimi.js +3 -2
- package/adapters/opencode.js +33 -122
- package/agents/review-coordinator.md +9 -6
- package/docs/AGENT-CONTEXT.md +21 -11
- package/docs/ARCHITECTURE.md +41 -13
- package/docs/PLAN.zh-CN.md +3 -2
- package/docs/ROADMAP.md +9 -5
- package/docs/RUNTIME-COMPAT-MATRIX.md +6 -6
- package/docs/STATE-DB-ACCESS-POLICY.md +27 -25
- package/docs/WORKFLOW-LIFECYCLE.md +266 -0
- package/hooks/README.md +6 -1
- package/hooks/active_task_context.py +22 -50
- package/hooks/context_spine.py +61 -332
- package/hooks/health_check.py +29 -18
- package/hooks/pre_stop_check.py +28 -33
- package/hooks/subagent_tracker.py +54 -85
- package/hooks/workflow_checkpoint.py +39 -47
- package/hooks/workflow_context.py +4 -9
- package/hooks/workflow_resume.py +48 -128
- package/mcp-server/breadcrumb.cjs +22 -0
- package/mcp-server/hook-event.cjs +34 -0
- package/mcp-server/lib/archive-journal.cjs +17 -5
- package/mcp-server/lib/baseline-workflow.cjs +158 -18
- package/mcp-server/lib/change-workflow.cjs +550 -85
- package/mcp-server/lib/context-spine.cjs +242 -24
- package/mcp-server/lib/doctor.cjs +33 -3
- package/mcp-server/lib/init-project.cjs +210 -16
- package/mcp-server/lib/plan-store.cjs +4 -1
- package/mcp-server/lib/prd-parser.cjs +14 -41
- package/mcp-server/lib/pricing.cjs +7 -10
- package/mcp-server/lib/project-breadcrumb.cjs +145 -0
- package/mcp-server/lib/projector.cjs +57 -3
- package/mcp-server/lib/spec-learning.cjs +79 -2
- package/mcp-server/lib/state-db.cjs +145 -8
- package/mcp-server/lib/state-ops.cjs +160 -9
- package/mcp-server/lib/task-expander.cjs +9 -38
- package/mcp-server/lib/workflow-state.cjs +2292 -0
- package/mcp-server/server.cjs +182 -50
- package/orchestrator/daemon.cjs +1 -2
- package/orchestrator/dispatch-rules.cjs +5 -31
- package/orchestrator/planner/plan-builder.cjs +21 -12
- package/package.json +14 -6
- package/skills/cc-collab/SKILL.md +2 -2
- package/skills/codex-collab/SKILL.md +2 -3
- package/skills/ultra-change/SKILL.md +53 -68
- package/skills/ultra-change/references/change-contract.md +36 -0
- package/skills/ultra-deliver/SKILL.md +69 -79
- package/skills/ultra-deliver/references/baseline-reconciliation.md +20 -0
- package/skills/ultra-dev/SKILL.md +54 -59
- package/skills/ultra-doctor/SKILL.md +40 -71
- package/skills/ultra-init/SKILL.md +96 -103
- package/skills/ultra-init/references/brownfield-adoption.md +2 -2
- package/skills/ultra-plan/SKILL.md +79 -75
- package/skills/ultra-plan/references/semantic-preflight.md +18 -0
- package/skills/ultra-research/SKILL.md +87 -60
- package/skills/ultra-research/references/00-problem-validation.md +36 -0
- package/skills/ultra-research/references/01-opportunity-discovery.md +33 -0
- package/skills/ultra-research/references/02-market-assessment.md +30 -0
- package/skills/ultra-research/references/03-competitive-landscape.md +31 -0
- package/skills/ultra-research/references/04-product-strategy.md +32 -0
- package/skills/ultra-research/references/05-assumptions-validation.md +31 -0
- package/skills/ultra-research/references/10-user-personas.md +29 -0
- package/skills/ultra-research/references/11-user-scenarios.md +28 -0
- package/skills/ultra-research/references/20-user-stories.md +30 -0
- package/skills/ultra-research/references/21-features-scope.md +29 -0
- package/skills/ultra-research/references/22-success-metrics.md +28 -0
- package/skills/ultra-research/references/30-architecture-context.md +30 -0
- package/skills/ultra-research/references/31-solution-strategy.md +28 -0
- package/skills/ultra-research/references/32-building-blocks.md +28 -0
- package/skills/ultra-research/references/40-deployment.md +29 -0
- package/skills/ultra-research/references/41-quality-risks.md +28 -0
- package/skills/ultra-research/references/99-synthesis.md +35 -0
- package/skills/ultra-review/SKILL.md +57 -73
- package/skills/ultra-review/references/review-modes.md +27 -0
- package/skills/ultra-review/references/unified-schema.md +25 -0
- package/skills/ultra-review/scripts/review_wait.py +40 -3
- package/skills/ultra-status/SKILL.md +41 -45
- package/skills/ultra-test/SKILL.md +48 -55
- package/skills/ultra-verify/SKILL.md +22 -31
- package/skills/ultra-verify/references/{confidence-system.md → evidence-status.md} +3 -3
- package/skills/ultra-verify/scripts/verify_wait.py +54 -54
- package/spec/cli-protocol.md +7 -2
- package/spec/mcp-tools.yaml +422 -73
- package/spec/schemas/baseline-reconciliation.v1.schema.json +73 -0
- package/spec/schemas/delivery-report.v1.schema.json +111 -0
- package/spec/schemas/mcp-tools.schema.json +1 -1
- package/spec/schemas/state-db.sql +82 -1
- package/spec/schemas/tasks.v4.5.schema.json +8 -1
- package/spec/schemas/test-report.v1.schema.json +194 -0
- package/ultra-tools/cli.cjs +1 -1
- package/ultra-tools/commands/migrate.cjs +3 -3
- package/ultra-tools/commands/status.cjs +213 -12
- package/.ultra-template/delivery-report.json +0 -9
- package/.ultra-template/test-report.json +0 -8
- package/adapters/_shared/tests/file-ops.test.cjs +0 -54
- package/adapters/_shared/tests/frontmatter.test.cjs +0 -47
- package/adapters/_shared/tests/handbook.test.cjs +0 -101
- package/adapters/_shared/tests/path-rewrite.test.cjs +0 -60
- package/adapters/_shared/tests/provenance.test.cjs +0 -133
- package/adapters/_shared/tests/resolve-target.test.cjs +0 -75
- package/adapters/_shared/tests/runtime-assets.test.cjs +0 -131
- package/adapters/_shared/tests/settings-merge.test.cjs +0 -85
- package/adapters/_shared/tests/validate.test.cjs +0 -30
- package/adapters/tests/claude.test.cjs +0 -137
- package/adapters/tests/codex-hook.test.cjs +0 -115
- package/adapters/tests/codex.test.cjs +0 -423
- package/adapters/tests/kimi-hook.test.cjs +0 -122
- package/adapters/tests/kimi.test.cjs +0 -259
- package/adapters/tests/opencode.test.cjs +0 -371
- package/mcp-server/lib/archive-journal.test.cjs +0 -35
- package/mcp-server/lib/baseline-workflow.test.cjs +0 -477
- package/mcp-server/lib/change-workflow.test.cjs +0 -971
- package/mcp-server/lib/context-spine.test.cjs +0 -93
- package/mcp-server/lib/doctor.test.cjs +0 -148
- package/mcp-server/lib/llm-client.cjs +0 -157
- package/mcp-server/lib/llm-client.test.cjs +0 -156
- package/mcp-server/lib/plan-store.test.cjs +0 -132
- package/mcp-server/lib/prd-parser.test.cjs +0 -171
- package/mcp-server/lib/runtime-state.test.cjs +0 -92
- package/mcp-server/lib/spec-learning.test.cjs +0 -67
- package/mcp-server/lib/state-db.test.cjs +0 -314
- package/mcp-server/lib/task-expander.test.cjs +0 -324
- package/mcp-server/lib/topo.test.cjs +0 -158
- package/mcp-server/tests/circuit-breaker.test.cjs +0 -125
- package/mcp-server/tests/commit-hash-flow.test.cjs +0 -117
- package/mcp-server/tests/concurrency-update.test.cjs +0 -96
- package/mcp-server/tests/concurrency.test.cjs +0 -112
- package/mcp-server/tests/db-ops.test.cjs +0 -121
- package/mcp-server/tests/init-project.test.cjs +0 -393
- package/mcp-server/tests/migrate.test.cjs +0 -232
- package/mcp-server/tests/projector.test.cjs +0 -162
- package/mcp-server/tests/server-contract.test.cjs +0 -1471
- package/mcp-server/tests/staleness.test.cjs +0 -190
- package/mcp-server/tests/state-db.test.cjs +0 -106
- package/mcp-server/tests/state-ops.test.cjs +0 -449
- package/mcp-server/tests/tagged-tasks.test.cjs +0 -163
- package/mcp-server/tests/telemetry.test.cjs +0 -219
- package/orchestrator/planner/expand-prompt.cjs +0 -62
- package/orchestrator/planner/expand-prompt.test.cjs +0 -52
- package/orchestrator/planner/plan-builder.test.cjs +0 -165
- package/orchestrator/planner/prd-prompt.cjs +0 -44
- package/orchestrator/planner/prd-prompt.test.cjs +0 -30
- package/orchestrator/tests/auto-merge.test.cjs +0 -216
- package/orchestrator/tests/daemon.test.cjs +0 -311
- package/orchestrator/tests/dispatch-rules.test.cjs +0 -124
- package/orchestrator/tests/parallel-orchestrator.test.cjs +0 -233
- package/orchestrator/tests/phase-8b-gate.test.cjs +0 -183
- package/orchestrator/tests/recovery.test.cjs +0 -190
- package/orchestrator/tests/session-runner.test.cjs +0 -314
- package/orchestrator/tests/skill-miner.test.cjs +0 -147
- package/orchestrator/tests/worktree-manager.test.cjs +0 -148
- package/skills/ultra-research/references/architecture.md +0 -38
- package/skills/ultra-research/references/problem-product.md +0 -39
- package/skills/ultra-research/references/quality-delivery.md +0 -34
- package/skills/ultra-research/references/synthesis.md +0 -38
- package/skills/ultra-research/references/users-scope.md +0 -40
- package/ultra-tools/legacy-memory.test.cjs +0 -80
- package/ultra-tools/status-command.test.cjs +0 -181
- package/ultra-tools/system-command.test.cjs +0 -309
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
> risks R21 / R25.
|
|
5
5
|
|
|
6
6
|
`.ultra/state.db` is the only authoritative state store for baselines, changes,
|
|
7
|
-
tasks, events, sessions, incidents, projections, telemetry, and spec references
|
|
7
|
+
tasks, workflow runs/steps, events, sessions, incidents, projections, telemetry, and spec references
|
|
8
8
|
(D18, D52, D54). Every process
|
|
9
9
|
that touches it must follow the rules below; deviations are bugs.
|
|
10
10
|
|
|
11
11
|
## 1. Three-role write matrix
|
|
12
12
|
|
|
13
|
-
| Role | tasks | baselines | change/artifact state | events | sessions | telemetry | specs_refs | migration_history |
|
|
13
|
+
| Role | tasks | baselines | change/workflow/artifact state | events | sessions | telemetry | specs_refs | migration_history |
|
|
14
14
|
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
15
15
|
| **MCP server** (single writer for mutables) | RW | RW | RW | RW | RW | RW | RW | RW |
|
|
16
16
|
| **CLI** (`ultra-tools …`) | R | RW (init only) | R | RW (append-only) | R | R | R | RW (migration only) |
|
|
@@ -31,7 +31,11 @@ write API for normal task, change, session, or baseline lifecycle updates.
|
|
|
31
31
|
The append-only carve-out for `events` exists because `events.id INTEGER
|
|
32
32
|
PRIMARY KEY AUTOINCREMENT` makes concurrent inserts collision-free under
|
|
33
33
|
WAL + `busy_timeout`. This lets hooks and short-lived CLI invocations
|
|
34
|
-
record audit
|
|
34
|
+
record audit observations without paying the cost of a full MCP round trip.
|
|
35
|
+
It does not grant lifecycle authority: external writers and public
|
|
36
|
+
`task.append_event` use the published observation allowlist, while lifecycle event
|
|
37
|
+
names are emitted only inside the mutation that owns the corresponding state change.
|
|
38
|
+
Consumers must verify mutable rows rather than infer success from an event name.
|
|
35
39
|
|
|
36
40
|
## 2. Connection discipline
|
|
37
41
|
|
|
@@ -40,31 +44,27 @@ Every process **must**:
|
|
|
40
44
|
1. Open the database with WAL + `busy_timeout=5000` + `foreign_keys=ON`.
|
|
41
45
|
Use `mcp-server/lib/state-db.cjs` `openStateDb` so the pragmas are
|
|
42
46
|
applied uniformly.
|
|
43
|
-
2. Wrap every
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
2. Wrap every mutable state operation with `state-ops.cjs` `tx(db, fn)`. The
|
|
48
|
+
helper calls better-sqlite3's immediate transaction variant, so the writer
|
|
49
|
+
lock is acquired before user code runs and the whole operation rolls back on
|
|
50
|
+
failure.
|
|
51
|
+
3. Retry the complete transaction up to **10 attempts** on `SQLITE_BUSY`, using
|
|
52
|
+
decorrelated jitter from a 50 ms base with a 2 s cap. Never retry only a
|
|
53
|
+
suffix of a failed transaction or preserve partial state.
|
|
49
54
|
4. Close the connection in a `finally` block. WAL files (`-wal`,
|
|
50
55
|
`-shm`) are reclaimed on the last writer's close.
|
|
51
56
|
|
|
52
57
|
Reads never need explicit transactions; better-sqlite3 reads observe a
|
|
53
58
|
consistent snapshot under WAL.
|
|
54
59
|
|
|
55
|
-
## 3. WAL
|
|
60
|
+
## 3. WAL requirement
|
|
56
61
|
|
|
57
|
-
WAL is
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
writers fall back to short-burst contention; throughput drops but
|
|
64
|
-
correctness holds.
|
|
65
|
-
|
|
66
|
-
Detection happens at boot: `statvfs` of `.ultra/state.db`'s mount;
|
|
67
|
-
`f_type` ∈ `{NFS_SUPER_MAGIC, SMB_SUPER_MAGIC}` ⇒ refuse / downgrade.
|
|
62
|
+
WAL is part of the authority contract, not an optional performance setting.
|
|
63
|
+
`openStateDb` asks SQLite to enable WAL and checks the actual returned mode. If
|
|
64
|
+
the storage layer returns anything else, startup fails with
|
|
65
|
+
`STATE_DB_WAL_UNAVAILABLE`. Ultra does not silently downgrade to a different
|
|
66
|
+
concurrency model. Move `.ultra/state.db` to storage that supports SQLite WAL or
|
|
67
|
+
resolve the mount/runtime constraint before retrying.
|
|
68
68
|
|
|
69
69
|
## 4. Where each table is owned
|
|
70
70
|
|
|
@@ -73,9 +73,10 @@ Detection happens at boot: `statvfs` of `.ultra/state.db`'s mount;
|
|
|
73
73
|
| `baselines` | MCP server (`baseline.start` / `baseline.record` / `baseline.converge`); initialization and legacy-projection migration may create only the first draft or compatibility row |
|
|
74
74
|
| `tasks` | MCP server (`task.create` / `task.update` / `task.delete`) |
|
|
75
75
|
| `changes` | MCP server (`change.create` / `change.update` / `change.converge` / `change.archive`) |
|
|
76
|
+
| `workflow_runs`, `workflow_steps` | MCP server (`workflow.start` / `workflow.step` / `workflow.complete`); skills provide evidence inputs but never write rows directly |
|
|
76
77
|
| `artifacts`, `context_snapshots`, `spec_learning_candidates`, `trace_links` | MCP server through change lifecycle tools |
|
|
77
78
|
| `incidents`, `projection_jobs`, `event_consumers`, `circuit_breaker` | MCP server; backup-first doctor recovery may perform only documented mechanical transitions |
|
|
78
|
-
| `events` | MCP server
|
|
79
|
+
| `events` | MCP server for lifecycle events; approved processes and `task.append_event` for allowlisted append-only observations |
|
|
79
80
|
| `sessions` | MCP server (`session.spawn` / `session.close` / `session.heartbeat`); orchestrator may write status transitions |
|
|
80
81
|
| `telemetry` | MCP server (collected from tool-call wrappers); orchestrator may dump bulk samples |
|
|
81
82
|
| `specs_refs` | MCP server (rebuilt on `spec_changed` event); orchestrator may rebuild |
|
|
@@ -110,6 +111,7 @@ The contract on this page is enforced by:
|
|
|
110
111
|
appending to `events` simultaneously; asserts no `SQLITE_BUSY` escapes
|
|
111
112
|
the retry loop and the resulting `events.id` sequence has no gaps and
|
|
112
113
|
no duplicates.
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
- `mcp-server/tests/state-ops.test.cjs` — immediate transactions, rollback,
|
|
115
|
+
status transitions, task contracts, and event coupling.
|
|
116
|
+
- `mcp-server/lib/workflow-state.test.cjs` — ordered workflow transitions,
|
|
117
|
+
evidence/output requirements, blocking/resume, and cross-stage gates.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# Ultra Builder Pro workflow lifecycle
|
|
2
|
+
|
|
3
|
+
This document defines when Ultra writes authoritative state, how each workflow
|
|
4
|
+
advances, what invalidates evidence, and which decisions remain with the active
|
|
5
|
+
host and project owner. It is the operational companion to
|
|
6
|
+
[`ARCHITECTURE.md`](./ARCHITECTURE.md) and the machine contracts under `spec/`.
|
|
7
|
+
|
|
8
|
+
## 1. Authority boundaries
|
|
9
|
+
|
|
10
|
+
| Surface | Owns | Must not own |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| Active host and owner | Product judgment, research content, implementation, review findings, release authorization | Durable workflow status or fabricated evidence digests |
|
|
13
|
+
| Skill | One reusable procedure and its evidence requirements | Project state, static product doctrine, host-specific tool fiction |
|
|
14
|
+
| MCP | IDs, transitions, task contracts, evidence references, output hashes, gate verdicts, next action | Research prose, code generation, memory, or model calls |
|
|
15
|
+
| `.ultra/state.db` | Baseline, change, task, workflow, session, event, incident, projection, and evidence authority | External memory or code-graph payloads |
|
|
16
|
+
| Generated JSON and Markdown | Read-only projections and durable artifacts | Independent lifecycle authority |
|
|
17
|
+
| Hook | Compact DB-derived lifecycle observation, minimal event metadata, and projection protection | Generic engineering judgment, prompt/transcript capture, parallel lifecycle logs, or arbitrary edit blocking |
|
|
18
|
+
|
|
19
|
+
Prompt input can supply facts, content paths, reasons, owner decisions, and
|
|
20
|
+
evidence references. MCP reads the current repository and DB, validates those
|
|
21
|
+
inputs, hashes outputs, and derives status. Prompt input cannot override a task's
|
|
22
|
+
public seam, verification command, context references, workflow summary, gate
|
|
23
|
+
verdict, output digest, or next action.
|
|
24
|
+
|
|
25
|
+
Every change-bound research, plan, dev, test, review, and deliver run inherits
|
|
26
|
+
the baseline id from the owning change workflow. A Prompt cannot switch that
|
|
27
|
+
authority, and no new stage may start on an archived or cancelled change. Doctor
|
|
28
|
+
recovers a legacy change without this link into an explicitly blocked workflow;
|
|
29
|
+
it does not fabricate the missing provenance.
|
|
30
|
+
|
|
31
|
+
Ultra does not select an MVP. Product scope and delivery posture are owner
|
|
32
|
+
decisions. A reduced research mode is valid only for an explicitly bounded active
|
|
33
|
+
change with a recorded selection reason; initial greenfield and brownfield
|
|
34
|
+
baselines always use all seventeen research steps.
|
|
35
|
+
|
|
36
|
+
## 2. How `ultra-init` classifies a repository
|
|
37
|
+
|
|
38
|
+
`task.init_project` scans a bounded repository view while ignoring `.git`,
|
|
39
|
+
`.ultra`, dependencies, virtual environments, generated build output, and other
|
|
40
|
+
known non-source directories.
|
|
41
|
+
|
|
42
|
+
`auto` classification is deterministic:
|
|
43
|
+
|
|
44
|
+
- `brownfield` when delivered-system evidence exists: application source, tests,
|
|
45
|
+
deployment configuration, or persisted-state/schema evidence;
|
|
46
|
+
- `greenfield` when none of those signals exists. A Git repository, README,
|
|
47
|
+
package manifest, workspace manifest, or starter documentation alone does not
|
|
48
|
+
prove delivered behavior;
|
|
49
|
+
- `migrated` is never inferred from source. It is a compatibility state created
|
|
50
|
+
when older Ultra authority is preserved and upgraded. It requires a new
|
|
51
|
+
evidence-backed brownfield adoption before normal work.
|
|
52
|
+
|
|
53
|
+
The scan also records bounded signal paths, detected verification commands,
|
|
54
|
+
evidence-backed project type and technology signals, monorepo markers, candidate
|
|
55
|
+
workspace roots, and whether the scan limit was reached. Explicit owner-supplied
|
|
56
|
+
project type or stack metadata overrides detection without deleting the observed
|
|
57
|
+
signals. In a monorepo, the owner selects the repository scope; baseline
|
|
58
|
+
worktree digests and accepted dirty files are restricted to that scope.
|
|
59
|
+
|
|
60
|
+
Classification and readiness are separate. Initialization immediately creates
|
|
61
|
+
or resumes `.ultra/state.db`, installs only the required scaffold, records the
|
|
62
|
+
classification, opens an `init` workflow, and opens `full` research for
|
|
63
|
+
greenfield or `adoption` research for brownfield. Empty templates are not an
|
|
64
|
+
approved baseline.
|
|
65
|
+
|
|
66
|
+
## 3. Durable status machines
|
|
67
|
+
|
|
68
|
+
### Baseline
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
draft -> adopting -> ready -> superseded
|
|
72
|
+
|
|
|
73
|
+
-> blocked -> adopting
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- `draft`: greenfield authority exists but has not been established.
|
|
77
|
+
- `adopting`: brownfield or migrated evidence is being recorded.
|
|
78
|
+
- `blocked`: current baseline evidence, verification, scope, or approval cannot
|
|
79
|
+
converge.
|
|
80
|
+
- `ready`: research, evidence, repository snapshot, gaps, and approval converged.
|
|
81
|
+
- `superseded`: preserved historical baseline after an explicitly authorized
|
|
82
|
+
replacement.
|
|
83
|
+
|
|
84
|
+
`ready` is not trusted as a label alone. Every baseline/status/doctor/change gate
|
|
85
|
+
revalidates its persisted fields, current files, research outputs, revision and
|
|
86
|
+
worktree, known-red acceptance, blocking gaps, and approval provenance. An ordinary
|
|
87
|
+
active change may downgrade only the expected drift created after its completed
|
|
88
|
+
`bind-baseline` step to warnings; it cannot downgrade adoption, migration, missing
|
|
89
|
+
evidence, or structural blockers. Approved incident break-glass is the only other
|
|
90
|
+
execution exception and creates a mandatory reconciliation gap.
|
|
91
|
+
|
|
92
|
+
### Change
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
active <-> blocked -> ready -> archived
|
|
96
|
+
\--------------------------> cancelled
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Only a healthy `ready` baseline may authorize a new ordinary change. An incident
|
|
100
|
+
may bypass an unhealthy baseline only with a stored reason and approver; archive
|
|
101
|
+
then creates a blocking baseline-reconciliation gap.
|
|
102
|
+
|
|
103
|
+
### Task
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
pending -> in_progress -> completed
|
|
107
|
+
| |
|
|
108
|
+
v v
|
|
109
|
+
blocked <------+
|
|
110
|
+
|
|
|
111
|
+
-> pending
|
|
112
|
+
|
|
113
|
+
pending -> expanded -> completed
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
A task is executable only when its DB contract contains an observable outcome,
|
|
117
|
+
traceability, slice kind, public seam, exact verification command, acceptance
|
|
118
|
+
checks, context references, resolved documentation impact, owner, and valid
|
|
119
|
+
dependencies.
|
|
120
|
+
|
|
121
|
+
### Workflow run and step
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
run: active <-> blocked -> ready -> completed
|
|
125
|
+
\----> cancelled
|
|
126
|
+
|
|
127
|
+
step: pending -> in_progress -> completed
|
|
128
|
+
| |
|
|
129
|
+
v v
|
|
130
|
+
blocked ------> in_progress/completed
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Required steps execute in definition order. A step that requires evidence or an
|
|
134
|
+
output cannot complete without it. When the final required step completes, the
|
|
135
|
+
run becomes `ready`; `workflow.complete` revalidates the entire stage before
|
|
136
|
+
making it `completed`.
|
|
137
|
+
|
|
138
|
+
## 4. Write and verification lifecycle
|
|
139
|
+
|
|
140
|
+
| Stage | Authoritative writes | Completion verification | Next route |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| `init` | Baseline classification/scope, init run, research run, initialization event, projection job | DB/schema opens, scaffold/projection succeeds; baseline convergence later completes init | `research`, re-adoption, or `change` for an already-ready baseline |
|
|
143
|
+
| `research` | Ordered step evidence, decisions, typed semantic records with source digests, one immutable report per selected step, output paths and SHA-256 digests | Every report has the required structure; semantic kinds/attributes/source anchors are valid and current; full/adoption synthesis binds the current three specifications and distillate; all digests remain current | `baseline.record`, then approval/convergence; bounded change research returns to its change |
|
|
144
|
+
| baseline convergence | Spec/source/runtime refs, verification results, known failures, unknowns, gaps, branch/HEAD/worktree, approval | Full/adoption research complete; required discovery/product/architecture refs current; revision/worktree exact; blocking gaps resolved or explicitly accepted where allowed | `change` for every initial or daily outcome |
|
|
145
|
+
| `change` | Complete Change Contract, profile/risk rationale, research disposition, intent/delta artifacts, linked change run, initial context snapshot | Blocking decisions resolved; selected change research current; current plan task set matches DB; task-bound context is ready; one next action is derived | selected `research`, then `plan`, or `dev` for an already approved current plan |
|
|
146
|
+
| `plan` | Plan-step evidence, complete change-owned task rows, acceptance coverage matrix, change-bound `.ultra/execution-plan.json`, explicit plan approval | Every Change acceptance id is owned by a task; task trace targets resolve; quick has one task; ownership/dependencies valid; no cycles; exported topology and digest exactly match the current change task set | `dev` for the first dependency-ready task |
|
|
147
|
+
| `dev` | Task/session transitions, step evidence, immutable implementation context, completion/review references | Task completed; no live session; task contract unchanged; starting context and review artifacts valid; completion commits remain ancestors of current HEAD | Next task, then aggregate `test` |
|
|
148
|
+
| `test` | Immutable checking context and `.ultra/reports/tests/<workflow-id>.json` | Report change/task set, full HEAD, worktree digest, context digest, commands, public seam, blockers, and all acceptance/regression/integration/static/build/performance/security/recovery dimensions agree; every omission has a not-applicable rationale | `review` when passing, otherwise resume `dev`/`test` |
|
|
149
|
+
| `review` | Immutable review context, `task`/`change`/`plan` mode, worker selection provenance, two specialist axes, coordinated summary | Current diff/HEAD and context match; selected/skipped workers match recorded rationale; both axes complete; P0/P1 and axis verdicts deterministically derive final verdict | `deliver` only from approved `change` mode, otherwise resume implementation |
|
|
150
|
+
| `deliver` | Convergence context, verified learning resolutions, schema-validated semantic reconciliation manifest, change archive, durable release-authorization decision, immutable delivery report | Tasks/test/change-review current; every baseline update has an anchored before/after semantic record; `change.converge` derives evidence from DB and accepts no Prompt verdicts; archive and baseline transaction agree; external actions have evidence | Report completion or start the next `change` |
|
|
151
|
+
| `status` | None | Reads doctor, baseline, workflows, breadcrumb, tasks, sessions, Git, and DB-referenced reports | One exact current route |
|
|
152
|
+
| `doctor` | None by default; explicit repair writes only mechanical recovery state | Re-runs integrity, schema, workflow-output, projection, session, incident, archive, and install checks | Exact repair, restore/rebaseline decision, or workflow route |
|
|
153
|
+
|
|
154
|
+
Every mutating MCP operation appends an event and enqueues projection work when
|
|
155
|
+
the corresponding read-only view can change. Projection failure is recorded as
|
|
156
|
+
a retryable incident; it does not silently convert a failed write into success.
|
|
157
|
+
`task.append_event` accepts only non-authoritative observations. Lifecycle events are
|
|
158
|
+
emitted by their owning DB mutation and never act as a substitute state transition.
|
|
159
|
+
|
|
160
|
+
## 5. Context and prompt follow-through
|
|
161
|
+
|
|
162
|
+
`change.context` compiles an immutable Context Manifest v2 snapshot. It combines:
|
|
163
|
+
|
|
164
|
+
- the bound baseline/change/task identity;
|
|
165
|
+
- a role and lifecycle gate;
|
|
166
|
+
- DB-backed task outcome, public seam, verification command, and required refs;
|
|
167
|
+
- local file hashes, current HEAD, branch, and worktree digest;
|
|
168
|
+
- optional metadata-only external memory or graph references;
|
|
169
|
+
- advisory file/token/context-share budgets;
|
|
170
|
+
- readiness blockers and one DB-derived next action.
|
|
171
|
+
|
|
172
|
+
Critical stage workflows bind a matching snapshot as a durable output:
|
|
173
|
+
|
|
174
|
+
| Workflow | Required role | Required gate |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| `change` | `plan` or `implement` | `planning` or `implementation` |
|
|
177
|
+
| `dev` | `implement` | `implementation` |
|
|
178
|
+
| `test` | `check` | `verification` |
|
|
179
|
+
| `review` | `review` | `review` |
|
|
180
|
+
| `deliver` | `check` | `convergence` |
|
|
181
|
+
|
|
182
|
+
The snapshot path and digest are then carried into test, review, and delivery
|
|
183
|
+
reports. This prevents a later Prompt from claiming evidence gathered under a
|
|
184
|
+
different context. File and token budgets warn; they do not block legitimate
|
|
185
|
+
work. Missing authority, required refs, task contracts, outputs, approval, or
|
|
186
|
+
current gate evidence do block.
|
|
187
|
+
|
|
188
|
+
## 6. Invalidation rules
|
|
189
|
+
|
|
190
|
+
- Changing a task contract invalidates contexts and gates that depended on the
|
|
191
|
+
former contract.
|
|
192
|
+
- Changing required source/spec content invalidates the recorded output or
|
|
193
|
+
context digest.
|
|
194
|
+
- Changing a research semantic source invalidates that workflow even when its immutable
|
|
195
|
+
step report remains unchanged.
|
|
196
|
+
- Changing full HEAD or the worktree invalidates aggregate test, review, and
|
|
197
|
+
delivery evidence.
|
|
198
|
+
- A completed dev run remains valid across later task commits when its bound
|
|
199
|
+
task contract is unchanged and its recorded commits remain ancestors of the
|
|
200
|
+
current HEAD.
|
|
201
|
+
- Test, review, and delivery reports use workflow-id paths so a later run cannot
|
|
202
|
+
overwrite historical evidence.
|
|
203
|
+
- `.ultra` workflow artifacts are excluded from application-worktree drift, but
|
|
204
|
+
their own recorded SHA-256 digests are still authoritative.
|
|
205
|
+
- Generated `tasks.json` and task-context headers are projections. Manual edits
|
|
206
|
+
are overwritten and never repair DB authority.
|
|
207
|
+
|
|
208
|
+
## 7. Entry flows
|
|
209
|
+
|
|
210
|
+
### New project
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
ultra-init -> full research (17 steps) -> baseline approval
|
|
214
|
+
-> initial change + plan -> dev per task -> test -> review -> deliver
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Existing project
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
ultra-init -> brownfield adoption research (17 steps)
|
|
221
|
+
-> characterization and known-red evidence -> gap ledger -> owner approval
|
|
222
|
+
-> first selected change -> plan -> dev -> test -> review -> deliver
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Adoption records the system that exists. It does not force the owner to recreate
|
|
226
|
+
market, persona, or roadmap claims that cannot be supported; those remain
|
|
227
|
+
`Unknown` or explicit gaps while every semantic step is still processed.
|
|
228
|
+
|
|
229
|
+
### Earlier Ultra project
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
doctor/migrate with backup -> migrated compatibility authority
|
|
233
|
+
-> explicit brownfield re-adoption -> full convergence -> normal change loop
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Migration preserves prior files and rows but never carries old approval forward.
|
|
237
|
+
|
|
238
|
+
### Daily maintenance
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
ultra-status -> ultra-change -> plan if task contracts are absent
|
|
242
|
+
-> dev -> test -> review -> deliver -> reconciled baseline
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Quick changes shorten the artifact burden only where the machine contract allows;
|
|
246
|
+
they do not skip task ownership, executable acceptance, current checking, review,
|
|
247
|
+
or baseline reconciliation. Incidents add structured diagnosis and recovery
|
|
248
|
+
evidence rather than bypassing them.
|
|
249
|
+
|
|
250
|
+
## 8. Recovery and diagnosis
|
|
251
|
+
|
|
252
|
+
Use `system.doctor` for project authority and `ubp --doctor` for installed host
|
|
253
|
+
assets. Both are read-only unless an explicit project repair command is chosen.
|
|
254
|
+
|
|
255
|
+
During an explicit repair, a legacy active change that predates durable workflows gets
|
|
256
|
+
one blocked change run at `bind-baseline` with
|
|
257
|
+
`LEGACY_CHANGE_PROVENANCE_REQUIRED`; repair does not invent its evidence. Rebind it to
|
|
258
|
+
the re-adopted baseline and resume the same run before planning. Every plan must use
|
|
259
|
+
the exact baseline id stored by its owning change run; only an approved break-glass
|
|
260
|
+
incident may legitimately bind no baseline id.
|
|
261
|
+
|
|
262
|
+
Resume the same blocked workflow and current step after resolving its blocker.
|
|
263
|
+
Do not create parallel runs to escape state. Supported schema and projection
|
|
264
|
+
repairs are backup-first. A corrupt DB is preserved and requires an explicit
|
|
265
|
+
restore or rebaseline decision; neither action can manufacture research,
|
|
266
|
+
verification, or owner approval.
|
package/hooks/README.md
CHANGED
|
@@ -14,12 +14,17 @@ advisory workflow conditions into refusal gates.
|
|
|
14
14
|
| Before compact | `workflow_checkpoint.py` | Validate and atomically save a minimal workflow checkpoint |
|
|
15
15
|
| After compact/resume | `workflow_resume.py` | Prefer the DB breadcrumb; restore the minimal file checkpoint only when no active change owns recovery |
|
|
16
16
|
| Stop | `pre_stop_check.py` | Report an incomplete workflow boundary and allow stop |
|
|
17
|
-
| Subagent lifecycle | `subagent_tracker.py` | Append
|
|
17
|
+
| Subagent lifecycle | `subagent_tracker.py` | Append minimal start/stop metadata to the authoritative DB event stream |
|
|
18
18
|
|
|
19
19
|
The plugin deliberately does not capture prompts, tool observations, transcripts, summaries, or
|
|
20
20
|
cross-session memory or code-graph content. Generic command blocking and post-edit policy are
|
|
21
21
|
user/repository governance. Persistent Memory/graph content belongs to separately installed providers.
|
|
22
22
|
|
|
23
|
+
`subagent_tracker.py` passes only agent id/type and the host session id to the bundled
|
|
24
|
+
`hook-event.cjs` helper. The helper binds the current change/task and appends
|
|
25
|
+
`subagent_started` or `subagent_stopped` to `state.db`; it never stores transcript
|
|
26
|
+
paths, messages, or a parallel JSONL lifecycle log.
|
|
27
|
+
|
|
23
28
|
`context_spine.py` is an imported library, not an eighth lifecycle registration.
|
|
24
29
|
Registering it separately would duplicate hook execution. The checkpoint is a recovery artifact, not a second authority. A valid newer
|
|
25
30
|
live workflow wins; a newer valid checkpoint may restore a missing or older
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
"""Protect Ultra projections and restate an active task boundary before edits."""
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
|
-
import sqlite3
|
|
6
5
|
import sys
|
|
7
6
|
from pathlib import Path
|
|
8
7
|
|
|
9
|
-
from context_spine import read_breadcrumb, render_breadcrumb
|
|
8
|
+
from context_spine import ContextSpineError, find_root, read_breadcrumb, render_breadcrumb
|
|
10
9
|
|
|
11
|
-
TERMINAL = {"committed", "completed", "done", "cancelled"}
|
|
12
10
|
TASKS_PROJECTION = Path(".ultra/tasks/tasks.json")
|
|
13
11
|
|
|
14
12
|
|
|
@@ -34,58 +32,32 @@ def main() -> None:
|
|
|
34
32
|
except json.JSONDecodeError as exc:
|
|
35
33
|
print(f"[active_task_context] invalid hook input: {exc}", file=sys.stderr)
|
|
36
34
|
data = {}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
(ultra / "state.db").is_file()
|
|
43
|
-
or state_file.is_file()
|
|
44
|
-
or (ultra / "changes" / "active").is_dir()
|
|
45
|
-
)
|
|
46
|
-
if not initialized:
|
|
47
|
-
continue
|
|
48
|
-
if targets_tasks_projection(data, root):
|
|
49
|
-
print(json.dumps({"hookSpecificOutput": {
|
|
50
|
-
"hookEventName": "PreToolUse",
|
|
51
|
-
"permissionDecision": "deny",
|
|
52
|
-
"permissionDecisionReason": (
|
|
53
|
-
"Refusing a direct write to the .ultra/tasks/tasks.json projection. "
|
|
54
|
-
".ultra/state.db is authoritative; use the Ultra MCP task tools and "
|
|
55
|
-
"run ultra-doctor when state or projection health is degraded."
|
|
56
|
-
),
|
|
57
|
-
}}))
|
|
58
|
-
return
|
|
59
|
-
try:
|
|
60
|
-
breadcrumb = read_breadcrumb(root)
|
|
61
|
-
except (sqlite3.Error, OSError) as exc:
|
|
62
|
-
print(f"[active_task_context] cannot inspect Context Spine: {exc}", file=sys.stderr)
|
|
63
|
-
breadcrumb = None
|
|
64
|
-
if breadcrumb and breadcrumb.get("task_id"):
|
|
65
|
-
print(json.dumps({"hookSpecificOutput": {
|
|
66
|
-
"hookEventName": "PreToolUse",
|
|
67
|
-
"additionalContext": render_breadcrumb(root, breadcrumb),
|
|
68
|
-
}}))
|
|
69
|
-
return
|
|
70
|
-
if not state_file.is_file():
|
|
71
|
-
break
|
|
72
|
-
try:
|
|
73
|
-
state = json.loads(state_file.read_text(encoding="utf-8"))
|
|
74
|
-
except (OSError, json.JSONDecodeError) as exc:
|
|
75
|
-
print(f"[active_task_context] cannot read {state_file}: {exc}", file=sys.stderr)
|
|
76
|
-
break
|
|
77
|
-
if not isinstance(state, dict) or state.get("status") in TERMINAL:
|
|
78
|
-
break
|
|
79
|
-
task = state.get("task_id", state.get("task", "unknown"))
|
|
80
|
-
step = state.get("step", "unknown")
|
|
35
|
+
root = find_root(Path(data.get("cwd") or Path.cwd()).resolve())
|
|
36
|
+
if root is None:
|
|
37
|
+
print(json.dumps({}))
|
|
38
|
+
return
|
|
39
|
+
if targets_tasks_projection(data, root):
|
|
81
40
|
print(json.dumps({"hookSpecificOutput": {
|
|
82
41
|
"hookEventName": "PreToolUse",
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
"
|
|
42
|
+
"permissionDecision": "deny",
|
|
43
|
+
"permissionDecisionReason": (
|
|
44
|
+
"Refusing a direct write to the .ultra/tasks/tasks.json projection. "
|
|
45
|
+
".ultra/state.db is authoritative; use the Ultra MCP task tools and "
|
|
46
|
+
"run ultra-doctor when state or projection health is degraded."
|
|
86
47
|
),
|
|
87
48
|
}}))
|
|
88
49
|
return
|
|
50
|
+
try:
|
|
51
|
+
breadcrumb = read_breadcrumb(root)
|
|
52
|
+
except ContextSpineError as exc:
|
|
53
|
+
print(f"[active_task_context] cannot inspect Context Spine: {exc}", file=sys.stderr)
|
|
54
|
+
breadcrumb = None
|
|
55
|
+
if breadcrumb and breadcrumb.get("change_id"):
|
|
56
|
+
print(json.dumps({"hookSpecificOutput": {
|
|
57
|
+
"hookEventName": "PreToolUse",
|
|
58
|
+
"additionalContext": render_breadcrumb(root, breadcrumb),
|
|
59
|
+
}}))
|
|
60
|
+
return
|
|
89
61
|
print(json.dumps({}))
|
|
90
62
|
|
|
91
63
|
|