ultra-builder-pro-cli 0.26.1 → 3.0.2
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/contexts/TEMPLATE.md +64 -29
- package/.ultra-template/north-star.md +36 -30
- package/.ultra-template/project-brief.md +28 -0
- package/.ultra-template/specs/product.md +4 -0
- package/.ultra-template/specs/research-distillate.md +8 -0
- package/.ultra-template/tasks.json +1 -0
- package/.ultra-template/test-report.json +18 -1
- package/CHANGELOG.md +227 -1
- package/README.md +161 -59
- package/adapters/_shared/host-profile.cjs +68 -12
- package/adapters/_shared/plugin-core.cjs +4 -5
- package/adapters/_shared/runtime-assets.cjs +11 -2
- package/adapters/zcode.js +375 -0
- package/bin/delegate-worker.cjs +20 -0
- package/bin/delegate.cjs +94 -25
- package/bin/install.js +11 -6
- package/docs/ARCHITECTURE.md +109 -25
- package/docs/ARTIFACT-AUTHORITY.md +204 -30
- package/docs/DECISIONS.md +141 -10
- package/docs/PHILOSOPHY.md +61 -8
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +6 -0
- package/docs/RUNTIME-COMPAT-MATRIX.md +106 -13
- package/docs/SKILL-AUTHORING.md +14 -9
- package/docs/WORKFLOW-LIFECYCLE.md +211 -53
- package/docs/evals/adversarial-review-2026-08-14.md +84 -0
- package/docs/evals/zcode-automation-2026-08-14.md +103 -0
- package/hooks/README.md +31 -3
- package/hooks/_common.py +1699 -33
- package/hooks/adapters/zcode.py +227 -0
- package/hooks/compact_context.py +176 -17
- package/hooks/mid_workflow_recall.py +27 -5
- package/hooks/post_edit_guard.py +133 -23
- package/hooks/session_context.py +722 -11
- package/package.json +6 -3
- package/skills/ultra-change/SKILL.md +84 -64
- package/skills/ultra-change/references/change-contract.md +130 -32
- package/skills/ultra-change/references/execution-grant.md +109 -0
- package/skills/ultra-change/references/primary-transfer.md +273 -0
- package/skills/ultra-change/scripts/validate_primary_transfer.cjs +1928 -0
- package/skills/ultra-delegate/SKILL.md +38 -5
- package/skills/ultra-delegate/references/delegation-contract.md +21 -1
- package/skills/ultra-deliver/SKILL.md +123 -44
- package/skills/ultra-deliver/references/baseline-reconciliation.md +5 -3
- package/skills/ultra-dev/SKILL.md +173 -43
- package/skills/ultra-grilling/SKILL.md +19 -16
- package/skills/ultra-grilling/references/reframing.md +7 -3
- package/skills/ultra-init/SKILL.md +99 -87
- package/skills/ultra-init/references/brownfield-adoption.md +23 -40
- package/skills/ultra-init/scripts/init_project.cjs +968 -21
- package/skills/ultra-plan/SKILL.md +83 -46
- package/skills/ultra-plan/references/task-evidence-v2.md +300 -0
- package/skills/ultra-plan/scripts/validate_task_evidence.cjs +859 -0
- package/skills/ultra-research/SKILL.md +119 -68
- package/skills/ultra-research/references/{03-competitive-landscape.md → 03-alternatives.md} +6 -6
- package/skills/ultra-research/references/04-product-strategy.md +11 -2
- package/skills/ultra-research/references/21-features-scope.md +8 -0
- package/skills/ultra-research/references/22-success-metrics.md +9 -4
- package/skills/ultra-research/references/99-synthesis.md +25 -1
- package/skills/ultra-research/references/north-star-v2.md +168 -0
- package/skills/ultra-research/references/wayfinding.md +50 -0
- package/skills/ultra-research/scripts/validate_north_star.cjs +1174 -0
- package/skills/ultra-review/SKILL.md +201 -24
- package/skills/ultra-review/references/adversarial-evaluation.md +31 -0
- package/skills/ultra-review/references/spec.md +5 -0
- package/skills/ultra-review/references/unified-schema.md +146 -11
- package/skills/ultra-review/references/worker-packet.md +151 -8
- package/skills/ultra-review/scripts/review_wait.py +2653 -63
- package/skills/ultra-status/SKILL.md +146 -32
- package/skills/ultra-tdd/SKILL.md +14 -4
- package/skills/ultra-tdd/references/test-execution.md +6 -1
- package/skills/ultra-test/SKILL.md +157 -15
- package/skills/ultra-test/scripts/validate_review_transport.cjs +549 -0
- package/skills/ultra-test/scripts/worktree_digest.cjs +551 -29
- package/skills/ultra-think/SKILL.md +5 -10
- package/skills/ultra-think/references/interaction-boundary.md +2 -1
package/hooks/post_edit_guard.py
CHANGED
|
@@ -3,17 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
-
import json
|
|
7
6
|
import re
|
|
8
7
|
from datetime import datetime, timezone
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
|
|
11
10
|
from _common import (
|
|
12
|
-
|
|
11
|
+
current_task_selection,
|
|
13
12
|
emit_context,
|
|
14
|
-
|
|
13
|
+
normalized_task_id,
|
|
14
|
+
project_relative_path,
|
|
15
15
|
project_root,
|
|
16
|
+
read_derived_json,
|
|
16
17
|
read_payload,
|
|
18
|
+
read_stable_project_file_snapshot,
|
|
19
|
+
render_task_diagnostics,
|
|
20
|
+
task_sections,
|
|
17
21
|
write_json_atomic,
|
|
18
22
|
)
|
|
19
23
|
|
|
@@ -26,25 +30,59 @@ DIMENSIONS = (
|
|
|
26
30
|
"vertical_slice",
|
|
27
31
|
"spec_trace",
|
|
28
32
|
)
|
|
33
|
+
PROGRESS_SNAPSHOT_MAX_BYTES = 1024 * 1024
|
|
34
|
+
TRACE_SOURCE_SNAPSHOT_MAX_BYTES = 8 * 1024 * 1024
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
def slug(value: str) -> str:
|
|
32
38
|
return re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
|
|
33
39
|
|
|
34
40
|
|
|
35
|
-
def trace_observation(root: Path, task: dict)
|
|
41
|
+
def trace_observation(root: Path, task: dict):
|
|
36
42
|
trace = task.get("trace_to")
|
|
37
43
|
if not isinstance(trace, str) or "#" not in trace:
|
|
38
|
-
return "missing"
|
|
44
|
+
return "missing", None
|
|
39
45
|
name, anchor = trace.rsplit("#", 1)
|
|
40
|
-
|
|
41
|
-
if
|
|
42
|
-
return "missing"
|
|
46
|
+
relative = project_relative_path(name, ultra_default=True)
|
|
47
|
+
if relative is None:
|
|
48
|
+
return "missing", None
|
|
49
|
+
snapshot, failure = read_stable_project_file_snapshot(
|
|
50
|
+
root,
|
|
51
|
+
relative,
|
|
52
|
+
max_bytes=TRACE_SOURCE_SNAPSHOT_MAX_BYTES,
|
|
53
|
+
code_prefix="trace_source_snapshot",
|
|
54
|
+
label="Task trace source",
|
|
55
|
+
)
|
|
56
|
+
if snapshot is None or failure is not None:
|
|
57
|
+
diagnostic = dict(failure) if failure is not None else {
|
|
58
|
+
"code": "trace_source_snapshot_read_error",
|
|
59
|
+
"message": "Task trace source could not be observed.",
|
|
60
|
+
"path": str(root / relative),
|
|
61
|
+
}
|
|
62
|
+
diagnostic["repair"] = (
|
|
63
|
+
"Restore the trace source as one stable readable regular UTF-8 file and retry "
|
|
64
|
+
"PostToolUse; spec_trace remains missing until it is observed."
|
|
65
|
+
)
|
|
66
|
+
return "missing", diagnostic
|
|
43
67
|
try:
|
|
44
|
-
|
|
45
|
-
except
|
|
46
|
-
return "missing"
|
|
47
|
-
|
|
68
|
+
text = snapshot["bytes"].decode("utf-8")
|
|
69
|
+
except UnicodeDecodeError:
|
|
70
|
+
return "missing", {
|
|
71
|
+
"code": "trace_source_snapshot_invalid_utf8",
|
|
72
|
+
"message": "Task trace source must be valid UTF-8 before it can be observed.",
|
|
73
|
+
"path": snapshot["path"],
|
|
74
|
+
"repair": (
|
|
75
|
+
"Restore the trace source as valid UTF-8 and retry PostToolUse; spec_trace "
|
|
76
|
+
"remains missing until it is observed."
|
|
77
|
+
),
|
|
78
|
+
}
|
|
79
|
+
headings = re.findall(r"^#{1,6}\s+(.+?)\s*$", text, re.MULTILINE)
|
|
80
|
+
observation = (
|
|
81
|
+
"observed"
|
|
82
|
+
if slug(anchor) in {slug(heading) for heading in headings}
|
|
83
|
+
else "missing"
|
|
84
|
+
)
|
|
85
|
+
return observation, None
|
|
48
86
|
|
|
49
87
|
|
|
50
88
|
def main() -> int:
|
|
@@ -52,8 +90,31 @@ def main() -> int:
|
|
|
52
90
|
root = project_root(payload) # Idle guard: no `.ultra/` means silent exit.
|
|
53
91
|
if root is None:
|
|
54
92
|
return 0
|
|
55
|
-
|
|
93
|
+
selection = current_task_selection(root)
|
|
94
|
+
task = selection["task"]
|
|
56
95
|
if not task:
|
|
96
|
+
diagnostics = render_task_diagnostics(selection["diagnostics"])
|
|
97
|
+
if diagnostics:
|
|
98
|
+
emit_context(
|
|
99
|
+
"PostToolUse",
|
|
100
|
+
"Ultra task selection diagnostic:\n" + diagnostics,
|
|
101
|
+
)
|
|
102
|
+
return 0
|
|
103
|
+
sections = task_sections(root, task)
|
|
104
|
+
if not sections["context_available"]:
|
|
105
|
+
context_diagnostics = [
|
|
106
|
+
diagnostic
|
|
107
|
+
for diagnostic in sections["diagnostics"]
|
|
108
|
+
if str(diagnostic.get("code") or "").startswith("task_context_")
|
|
109
|
+
]
|
|
110
|
+
emit_context(
|
|
111
|
+
"PostToolUse",
|
|
112
|
+
"Ultra task context diagnostic:\n"
|
|
113
|
+
+ render_task_diagnostics(context_diagnostics),
|
|
114
|
+
)
|
|
115
|
+
return 0
|
|
116
|
+
task_id = normalized_task_id(task.get("id"))
|
|
117
|
+
if task_id is None:
|
|
57
118
|
return 0
|
|
58
119
|
tool_input = payload.get("tool_input")
|
|
59
120
|
tool_input = tool_input if isinstance(tool_input, dict) else {}
|
|
@@ -62,19 +123,39 @@ def main() -> int:
|
|
|
62
123
|
if changed:
|
|
63
124
|
try:
|
|
64
125
|
relative = str(Path(changed).resolve().relative_to(root))
|
|
65
|
-
except ValueError:
|
|
126
|
+
except (OSError, RuntimeError, ValueError):
|
|
66
127
|
relative = ""
|
|
67
128
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
129
|
+
progress_relative = Path(".ultra") / "progress" / f"{task_id}.json"
|
|
130
|
+
progress, read_failure = read_derived_json(
|
|
131
|
+
root,
|
|
132
|
+
progress_relative,
|
|
133
|
+
max_bytes=PROGRESS_SNAPSHOT_MAX_BYTES,
|
|
134
|
+
code_prefix="progress_snapshot",
|
|
135
|
+
label="Task progress observation",
|
|
136
|
+
)
|
|
137
|
+
diagnostics = []
|
|
138
|
+
if read_failure is not None:
|
|
139
|
+
code = read_failure.get("code", "")
|
|
140
|
+
if code.endswith("_missing"):
|
|
141
|
+
progress = {}
|
|
142
|
+
elif code.endswith(("_invalid_utf8", "_invalid_json", "_invalid_root")):
|
|
143
|
+
diagnostics.append(read_failure)
|
|
144
|
+
progress = {}
|
|
145
|
+
else:
|
|
146
|
+
emit_context(
|
|
147
|
+
"PostToolUse",
|
|
148
|
+
"Ultra progress diagnostic:\n"
|
|
149
|
+
+ render_task_diagnostics([read_failure]),
|
|
150
|
+
)
|
|
151
|
+
return 0
|
|
152
|
+
if progress is None:
|
|
72
153
|
progress = {}
|
|
73
154
|
if not isinstance(progress, dict):
|
|
74
155
|
progress = {}
|
|
75
156
|
existing_evidence = progress.get("evidence")
|
|
76
157
|
existing_evidence = existing_evidence if isinstance(existing_evidence, dict) else {}
|
|
77
|
-
progress["task_id"] =
|
|
158
|
+
progress["task_id"] = task_id
|
|
78
159
|
progress["evidence"] = {
|
|
79
160
|
name: existing_evidence.get(name, "unknown")
|
|
80
161
|
if isinstance(existing_evidence.get(name, "unknown"), str)
|
|
@@ -89,14 +170,43 @@ def main() -> int:
|
|
|
89
170
|
progress["touched_files"].append(relative)
|
|
90
171
|
if re.search(r"(?:^|/)(?:test|tests|__tests__)/|(?:\.test|\.spec)\.", relative, re.IGNORECASE):
|
|
91
172
|
progress["evidence"]["tests_written"] = "observed"
|
|
92
|
-
|
|
173
|
+
trace_value, trace_failure = trace_observation(root, task)
|
|
174
|
+
progress["evidence"]["spec_trace"] = trace_value
|
|
175
|
+
if trace_failure is not None:
|
|
176
|
+
diagnostics.append(trace_failure)
|
|
93
177
|
progress["updated_at"] = datetime.now(timezone.utc).isoformat()
|
|
94
|
-
write_json_atomic(
|
|
178
|
+
write_failure = write_json_atomic(
|
|
179
|
+
root,
|
|
180
|
+
progress_relative,
|
|
181
|
+
progress,
|
|
182
|
+
max_bytes=PROGRESS_SNAPSHOT_MAX_BYTES,
|
|
183
|
+
code_prefix="progress_write",
|
|
184
|
+
label="Task progress observation",
|
|
185
|
+
)
|
|
186
|
+
if write_failure is not None:
|
|
187
|
+
diagnostics.append(write_failure)
|
|
188
|
+
emit_context(
|
|
189
|
+
"PostToolUse",
|
|
190
|
+
"Ultra progress diagnostic:\n"
|
|
191
|
+
+ render_task_diagnostics(diagnostics),
|
|
192
|
+
)
|
|
193
|
+
return 0
|
|
95
194
|
|
|
96
|
-
|
|
195
|
+
non_observed = [
|
|
196
|
+
name
|
|
197
|
+
for name, value in progress["evidence"].items()
|
|
198
|
+
if value != "observed"
|
|
199
|
+
]
|
|
200
|
+
parts = []
|
|
201
|
+
if diagnostics:
|
|
202
|
+
parts.append("Ultra progress diagnostic:\n" + render_task_diagnostics(diagnostics))
|
|
203
|
+
parts.append(
|
|
204
|
+
f"Ultra evidence sensor updated task {task_id}. Still non-observed: "
|
|
205
|
+
f"{', '.join(non_observed) or 'none'}."
|
|
206
|
+
)
|
|
97
207
|
emit_context(
|
|
98
208
|
"PostToolUse",
|
|
99
|
-
|
|
209
|
+
"\n\n".join(parts),
|
|
100
210
|
)
|
|
101
211
|
return 0
|
|
102
212
|
|