@blxzer/cursor-trellis 0.3.5 → 0.4.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/CHANGELOG.md +69 -0
- package/README.md +13 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/goal/index.d.ts +3 -0
- package/dist/commands/goal/index.d.ts.map +1 -0
- package/dist/commands/goal/index.js +159 -0
- package/dist/commands/goal/index.js.map +1 -0
- package/dist/commands/goal/review.d.ts +6 -0
- package/dist/commands/goal/review.d.ts.map +1 -0
- package/dist/commands/goal/review.js +28 -0
- package/dist/commands/goal/review.js.map +1 -0
- package/dist/commands/sdk/run.d.ts.map +1 -1
- package/dist/commands/sdk/run.js +2 -27
- package/dist/commands/sdk/run.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +5 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +51 -2
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +4 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +4 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/goal/action-packet.d.ts +89 -0
- package/dist/goal/action-packet.d.ts.map +1 -0
- package/dist/goal/action-packet.js +113 -0
- package/dist/goal/action-packet.js.map +1 -0
- package/dist/goal/audit.d.ts +14 -0
- package/dist/goal/audit.d.ts.map +1 -0
- package/dist/goal/audit.js +12 -0
- package/dist/goal/audit.js.map +1 -0
- package/dist/goal/constants.d.ts +26 -0
- package/dist/goal/constants.d.ts.map +1 -0
- package/dist/goal/constants.js +24 -0
- package/dist/goal/constants.js.map +1 -0
- package/dist/goal/paths.d.ts +8 -0
- package/dist/goal/paths.d.ts.map +1 -0
- package/dist/goal/paths.js +36 -0
- package/dist/goal/paths.js.map +1 -0
- package/dist/goal/preflight.d.ts +21 -0
- package/dist/goal/preflight.d.ts.map +1 -0
- package/dist/goal/preflight.js +97 -0
- package/dist/goal/preflight.js.map +1 -0
- package/dist/goal/review-seam.d.ts +44 -0
- package/dist/goal/review-seam.d.ts.map +1 -0
- package/dist/goal/review-seam.js +153 -0
- package/dist/goal/review-seam.js.map +1 -0
- package/dist/goal/reviewer-rules.d.ts +13 -0
- package/dist/goal/reviewer-rules.d.ts.map +1 -0
- package/dist/goal/reviewer-rules.js +153 -0
- package/dist/goal/reviewer-rules.js.map +1 -0
- package/dist/goal/reviewer.d.ts +9 -0
- package/dist/goal/reviewer.d.ts.map +1 -0
- package/dist/goal/reviewer.js +54 -0
- package/dist/goal/reviewer.js.map +1 -0
- package/dist/goal/runtime.d.ts +32 -0
- package/dist/goal/runtime.d.ts.map +1 -0
- package/dist/goal/runtime.js +242 -0
- package/dist/goal/runtime.js.map +1 -0
- package/dist/goal/sdk-client.d.ts +10 -0
- package/dist/goal/sdk-client.d.ts.map +1 -0
- package/dist/goal/sdk-client.js +34 -0
- package/dist/goal/sdk-client.js.map +1 -0
- package/dist/goal/state.d.ts +40 -0
- package/dist/goal/state.d.ts.map +1 -0
- package/dist/goal/state.js +37 -0
- package/dist/goal/state.js.map +1 -0
- package/dist/goal/task-triggers.d.ts +15 -0
- package/dist/goal/task-triggers.d.ts.map +1 -0
- package/dist/goal/task-triggers.js +23 -0
- package/dist/goal/task-triggers.js.map +1 -0
- package/dist/goal/walls.d.ts +12 -0
- package/dist/goal/walls.d.ts.map +1 -0
- package/dist/goal/walls.js +65 -0
- package/dist/goal/walls.js.map +1 -0
- package/dist/goal/worker-prompt.d.ts +13 -0
- package/dist/goal/worker-prompt.d.ts.map +1 -0
- package/dist/goal/worker-prompt.js +41 -0
- package/dist/goal/worker-prompt.js.map +1 -0
- package/dist/goal/worker.d.ts +42 -0
- package/dist/goal/worker.d.ts.map +1 -0
- package/dist/goal/worker.js +180 -0
- package/dist/goal/worker.js.map +1 -0
- package/dist/migrations/manifests/0.3.5.json +9 -0
- package/dist/migrations/manifests/0.3.6.json +9 -0
- package/dist/migrations/manifests/0.4.0.json +9 -0
- package/dist/templates/common/commands/continue.md +15 -3
- package/dist/templates/common/skills/check.md +7 -4
- package/dist/templates/cursor/agents/cstl-check.md +1 -0
- package/dist/templates/cursor/fixtures/expected-rules.d.ts.map +1 -1
- package/dist/templates/cursor/fixtures/expected-rules.js +6 -1
- package/dist/templates/cursor/fixtures/expected-rules.js.map +1 -1
- package/dist/templates/cursor/rules/cstl-cursor-modes.mdc +32 -0
- package/dist/templates/cursor/rules/cstl-triage.mdc +2 -4
- package/dist/templates/cursor/rules/retrieval-routing.mdc +26 -7
- package/dist/templates/markdown/index.d.ts +9 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +9 -0
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/spec/guides/artifact-locale-guide.md.txt +93 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +7 -7
- package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +38 -21
- package/dist/templates/markdown/spec/guides/cursor-native-modes-guide.md.txt +125 -0
- package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +10 -8
- package/dist/templates/markdown/spec/guides/debug-loop-guide.md.txt +227 -0
- package/dist/templates/markdown/spec/guides/goal-release-regression-runbook.md.txt +132 -0
- package/dist/templates/markdown/spec/guides/index.md.txt +144 -104
- package/dist/templates/markdown/spec/guides/injection-budget-guide.md.txt +111 -0
- package/dist/templates/markdown/spec/guides/prototype-guide.md.txt +139 -0
- package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +28 -6
- package/dist/templates/markdown/spec/guides/test-discipline-guide.md.txt +138 -0
- package/dist/templates/markdown/spec/guides/verification-strength-guide.md.txt +185 -0
- package/dist/templates/shared-hooks/session-start.py +10 -0
- package/dist/templates/trellis/config.yaml +18 -0
- package/dist/templates/trellis/index.d.ts +17 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +40 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/pool/README.md +103 -0
- package/dist/templates/trellis/pool/items/.gitkeep +0 -0
- package/dist/templates/trellis/pool/plan.md +26 -0
- package/dist/templates/trellis/scripts/common/artifact_locale.py +278 -0
- package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +37 -2
- package/dist/templates/trellis/scripts/common/config.py +39 -0
- package/dist/templates/trellis/scripts/common/injection_budget.py +317 -0
- package/dist/templates/trellis/scripts/common/parent_orchestration.py +161 -5
- package/dist/templates/trellis/scripts/common/pool_store.py +702 -0
- package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +9 -3
- package/dist/templates/trellis/scripts/common/session_context.py +32 -4
- package/dist/templates/trellis/scripts/common/session_memory.py +26 -0
- package/dist/templates/trellis/scripts/common/subagent_dispatch.py +74 -9
- package/dist/templates/trellis/scripts/common/task_context.py +18 -0
- package/dist/templates/trellis/scripts/common/task_dashboard.py +24 -1
- package/dist/templates/trellis/scripts/common/task_dependencies.py +673 -0
- package/dist/templates/trellis/scripts/common/task_gates.py +58 -5
- package/dist/templates/trellis/scripts/common/task_map.py +40 -8
- package/dist/templates/trellis/scripts/common/task_store.py +400 -39
- package/dist/templates/trellis/scripts/common/test_depends_mode_block.py +489 -0
- package/dist/templates/trellis/scripts/common/test_observable_defaults.py +135 -0
- package/dist/templates/trellis/scripts/common/test_pool_store.py +428 -0
- package/dist/templates/trellis/scripts/common/test_task_dependencies.py +345 -0
- package/dist/templates/trellis/scripts/cursor_retrieval_probe_prompt.md +14 -12
- package/dist/templates/trellis/scripts/generate_dispatch_prompt.py +182 -0
- package/dist/templates/trellis/scripts/injection_budget_probe.py +69 -0
- package/dist/templates/trellis/scripts/pool.py +192 -0
- package/dist/templates/trellis/scripts/retrieval_probe_matrix_template.json +3 -3
- package/dist/templates/trellis/scripts/spec_health_outcomes.py +160 -0
- package/dist/templates/trellis/scripts/task.py +85 -1
- package/dist/templates/trellis/scripts/verify_evidence_probe.py +138 -0
- package/dist/templates/trellis/tasks/locale/en/default-prd.md +19 -0
- package/dist/templates/trellis/tasks/locale/zh/default-prd.md +19 -0
- package/dist/templates/trellis/workflow.md +55 -5
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env python
|
|
2
2
|
"""
|
|
3
3
|
Task quality gate helpers.
|
|
4
4
|
|
|
@@ -15,6 +15,11 @@ from dataclasses import dataclass, field
|
|
|
15
15
|
from datetime import datetime, timezone
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
|
+
from .task_dependencies import (
|
|
19
|
+
describe_dependencies,
|
|
20
|
+
read_depends_mode,
|
|
21
|
+
scope_children_for_task,
|
|
22
|
+
)
|
|
18
23
|
from .task_map import (
|
|
19
24
|
get_child_state,
|
|
20
25
|
load_task_map,
|
|
@@ -144,6 +149,7 @@ STABLE_TASK_KEYS = (
|
|
|
144
149
|
"kind",
|
|
145
150
|
"mode",
|
|
146
151
|
"contract_epoch",
|
|
152
|
+
"depends_on",
|
|
147
153
|
)
|
|
148
154
|
|
|
149
155
|
|
|
@@ -161,6 +167,7 @@ class GateGuardResult:
|
|
|
161
167
|
is_full_task: bool = False
|
|
162
168
|
closeout_profile: str = "lite"
|
|
163
169
|
auto_gate_records: dict[str, dict] = field(default_factory=dict)
|
|
170
|
+
deps_blocking_summary: list[str] = field(default_factory=list)
|
|
164
171
|
|
|
165
172
|
|
|
166
173
|
def utc_now() -> str:
|
|
@@ -610,8 +617,19 @@ def validate_start_execution(
|
|
|
610
617
|
task_dir: Path,
|
|
611
618
|
task_data: dict | None,
|
|
612
619
|
approved: bool,
|
|
620
|
+
*,
|
|
621
|
+
ignore_deps: bool = False,
|
|
622
|
+
enforce_deps_block: bool = False,
|
|
613
623
|
) -> GateGuardResult:
|
|
614
|
-
"""Validate start-execution readiness.
|
|
624
|
+
"""Validate start-execution readiness.
|
|
625
|
+
|
|
626
|
+
Dependency policy (Plan B, per adjudication 05 §3.1/§3.2):
|
|
627
|
+
- enforce_deps_block=True is passed ONLY by the mutating `--approved` path.
|
|
628
|
+
mode=block + unmet deps then fail unless ignore_deps=True.
|
|
629
|
+
- mode=off silences dependency warnings entirely.
|
|
630
|
+
- every other path (--check, warn mode) keeps Plan A semantics: deps are
|
|
631
|
+
warnings that never fail the guard.
|
|
632
|
+
"""
|
|
615
633
|
errors: list[str] = []
|
|
616
634
|
if task_data is None:
|
|
617
635
|
return GateGuardResult(ok=False, errors=["task.json"])
|
|
@@ -691,6 +709,29 @@ def validate_start_execution(
|
|
|
691
709
|
if not approved:
|
|
692
710
|
errors.append("--approved is required for mutation")
|
|
693
711
|
|
|
712
|
+
warnings: list[str] = []
|
|
713
|
+
deps_blocking_summary: list[str] = []
|
|
714
|
+
if task_data is not None:
|
|
715
|
+
scope = scope_children_for_task(task_dir, task_data)
|
|
716
|
+
report = describe_dependencies(
|
|
717
|
+
task_dir,
|
|
718
|
+
task_data,
|
|
719
|
+
scope_children=scope,
|
|
720
|
+
)
|
|
721
|
+
depends_mode = read_depends_mode(task_data)
|
|
722
|
+
if enforce_deps_block and depends_mode == "block":
|
|
723
|
+
deps_blocking_summary = report.blocking_errors()
|
|
724
|
+
if ignore_deps:
|
|
725
|
+
warnings.extend(report.warnings())
|
|
726
|
+
else:
|
|
727
|
+
errors.extend(deps_blocking_summary)
|
|
728
|
+
elif depends_mode != "off":
|
|
729
|
+
warnings.extend(report.warnings())
|
|
730
|
+
if depends_mode == "block" and not enforce_deps_block:
|
|
731
|
+
warnings.append(
|
|
732
|
+
"dependency policy mode=block: --approved would fail unless --ignore-deps"
|
|
733
|
+
)
|
|
734
|
+
|
|
694
735
|
baseline_record = None
|
|
695
736
|
if not errors:
|
|
696
737
|
baseline_record = make_baseline_record(
|
|
@@ -700,12 +741,14 @@ def validate_start_execution(
|
|
|
700
741
|
return GateGuardResult(
|
|
701
742
|
ok=not errors,
|
|
702
743
|
errors=errors,
|
|
744
|
+
warnings=warnings,
|
|
703
745
|
contract_fingerprint=contract_fingerprint,
|
|
704
746
|
artifact_fingerprints=artifact_fingerprints,
|
|
705
747
|
required_gates=required_gates,
|
|
706
748
|
baseline_record=baseline_record,
|
|
707
749
|
is_full_task=full_task,
|
|
708
750
|
auto_gate_records=auto_gate_records,
|
|
751
|
+
deps_blocking_summary=deps_blocking_summary,
|
|
709
752
|
)
|
|
710
753
|
|
|
711
754
|
|
|
@@ -737,9 +780,19 @@ def validate_start_execution_check(
|
|
|
737
780
|
task_dir: Path,
|
|
738
781
|
task_data: dict | None,
|
|
739
782
|
) -> GateGuardResult:
|
|
740
|
-
"""Validate start-execution preflight without requiring approval.
|
|
741
|
-
|
|
742
|
-
|
|
783
|
+
"""Validate start-execution preflight without requiring approval.
|
|
784
|
+
|
|
785
|
+
NOTE (adjudication 05 §3.1 trap): the check path deliberately passes
|
|
786
|
+
enforce_deps_block=False — even when the task is in mode=block, --check
|
|
787
|
+
must never fail on dependencies; it only surfaces warnings. Only the
|
|
788
|
+
mutating --approved path may set enforce_deps_block=True.
|
|
789
|
+
"""
|
|
790
|
+
return validate_start_execution(
|
|
791
|
+
task_dir,
|
|
792
|
+
task_data,
|
|
793
|
+
approved=True,
|
|
794
|
+
enforce_deps_block=False,
|
|
795
|
+
)
|
|
743
796
|
|
|
744
797
|
|
|
745
798
|
def validate_transition_readiness(
|
|
@@ -127,6 +127,37 @@ def remove_child_from_task_map(
|
|
|
127
127
|
write_task_map(parent_dir, data, body, f"Unlinked Child `{child_name}`.")
|
|
128
128
|
|
|
129
129
|
|
|
130
|
+
def resolve_child_map_id(
|
|
131
|
+
parent_data: dict,
|
|
132
|
+
child_dir: Path,
|
|
133
|
+
child_data: dict | None = None,
|
|
134
|
+
) -> str:
|
|
135
|
+
"""Resolve task-map child id for a child directory (nested slash slugs)."""
|
|
136
|
+
structural = parent_data.get("children", [])
|
|
137
|
+
if not isinstance(structural, list):
|
|
138
|
+
structural = []
|
|
139
|
+
|
|
140
|
+
leaf = child_dir.name
|
|
141
|
+
if leaf in structural:
|
|
142
|
+
return leaf
|
|
143
|
+
|
|
144
|
+
if child_data:
|
|
145
|
+
for key in ("name", "id"):
|
|
146
|
+
value = child_data.get(key)
|
|
147
|
+
if isinstance(value, str) and value in structural:
|
|
148
|
+
return value
|
|
149
|
+
|
|
150
|
+
suffix_matches = [
|
|
151
|
+
cid
|
|
152
|
+
for cid in structural
|
|
153
|
+
if isinstance(cid, str) and (cid == leaf or cid.endswith(f"/{leaf}"))
|
|
154
|
+
]
|
|
155
|
+
if len(suffix_matches) == 1:
|
|
156
|
+
return suffix_matches[0]
|
|
157
|
+
|
|
158
|
+
return leaf
|
|
159
|
+
|
|
160
|
+
|
|
130
161
|
def set_child_state(
|
|
131
162
|
parent_dir: Path,
|
|
132
163
|
parent_data: dict,
|
|
@@ -183,7 +214,7 @@ def validate_parent_child_integration(
|
|
|
183
214
|
) -> list[str]:
|
|
184
215
|
"""Validate a Parent-controlled Child integration state transition."""
|
|
185
216
|
errors: list[str] = []
|
|
186
|
-
child_name = child_dir
|
|
217
|
+
child_name = resolve_child_map_id(parent_data, child_dir, child_data)
|
|
187
218
|
if state not in PARENT_CONTROLLED_STATES:
|
|
188
219
|
errors.append(f"state is not Parent-controlled: {state}")
|
|
189
220
|
if not _short_text(evidence):
|
|
@@ -295,10 +326,11 @@ def set_parent_child_integration_state(
|
|
|
295
326
|
if errors:
|
|
296
327
|
return False, errors
|
|
297
328
|
|
|
329
|
+
child_name = resolve_child_map_id(parent_data, child_dir, child_data)
|
|
298
330
|
data = ensure_task_map(parent_dir, parent_data, list(parent_data.get("children", [])))
|
|
299
|
-
child = get_child_entry(data,
|
|
331
|
+
child = get_child_entry(data, child_name)
|
|
300
332
|
if child is None:
|
|
301
|
-
return False, [f"child missing from task-map.md: {
|
|
333
|
+
return False, [f"child missing from task-map.md: {child_name}"]
|
|
302
334
|
|
|
303
335
|
child["state"] = state
|
|
304
336
|
child["evidence"] = evidence
|
|
@@ -316,12 +348,12 @@ def set_parent_child_integration_state(
|
|
|
316
348
|
queue = []
|
|
317
349
|
data["integration_queue"] = queue
|
|
318
350
|
if state == "integrating":
|
|
319
|
-
if
|
|
320
|
-
queue.append(
|
|
321
|
-
elif
|
|
322
|
-
data["integration_queue"] = [item for item in queue if item !=
|
|
351
|
+
if child_name not in queue:
|
|
352
|
+
queue.append(child_name)
|
|
353
|
+
elif child_name in queue:
|
|
354
|
+
data["integration_queue"] = [item for item in queue if item != child_name]
|
|
323
355
|
|
|
324
|
-
event = f"Parent set Child `{
|
|
356
|
+
event = f"Parent set Child `{child_name}` integration state to `{state}`. Evidence: {evidence}."
|
|
325
357
|
if ref:
|
|
326
358
|
event = f"{event} Ref: {ref}."
|
|
327
359
|
if merge_ref:
|