@deftai/directive-content 0.59.0 → 0.61.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 (190) hide show
  1. package/.githooks/pre-commit +10 -128
  2. package/.githooks/pre-push +8 -108
  3. package/Taskfile.yml +48 -58
  4. package/UPGRADING.md +19 -3
  5. package/docs/assets/directive-lifecycle-diagram.png +0 -0
  6. package/docs/directive-lifecycle.md +73 -0
  7. package/docs/getting-started.md +5 -1
  8. package/package.json +3 -3
  9. package/packs/skills/skills-pack-0.1.json +1 -1
  10. package/packs/strategies/strategies-pack-0.1.json +19 -19
  11. package/scm/github.md +37 -6
  12. package/skills/deft-directive-setup/SKILL.md +24 -15
  13. package/strategies/speckit.md +14 -14
  14. package/strategies/v0-20-contract.md +12 -1
  15. package/tasks/change.yml +16 -31
  16. package/tasks/ci.yml +8 -0
  17. package/tasks/commit.yml +12 -19
  18. package/tasks/core.yml +10 -0
  19. package/tasks/engine.yml +42 -0
  20. package/tasks/framework.yml +3 -0
  21. package/tasks/install.yml +20 -19
  22. package/tasks/migrate.yml +26 -15
  23. package/tasks/project.yml +26 -0
  24. package/tasks/toolchain.yml +15 -5
  25. package/tasks/vbrief.yml +4 -3
  26. package/tasks/verify.yml +12 -14
  27. package/templates/agents-entry.md +1 -1
  28. package/scripts/_agents_md.py +0 -494
  29. package/scripts/_cache_fetch.py +0 -635
  30. package/scripts/_cache_quota.py +0 -529
  31. package/scripts/_cache_refresh.py +0 -163
  32. package/scripts/_cache_validate.py +0 -209
  33. package/scripts/_content_root.py +0 -42
  34. package/scripts/_doctor_state.py +0 -277
  35. package/scripts/_event_detect.py +0 -305
  36. package/scripts/_events.py +0 -514
  37. package/scripts/_lifecycle_hygiene.py +0 -568
  38. package/scripts/_pathspec.py +0 -91
  39. package/scripts/_policy_show_cli.py +0 -266
  40. package/scripts/_precutover.py +0 -92
  41. package/scripts/_project_context.py +0 -224
  42. package/scripts/_project_definition_io.py +0 -164
  43. package/scripts/_relocate_snapshot.py +0 -209
  44. package/scripts/_relocate_states.py +0 -343
  45. package/scripts/_resolve_preflight_path.py +0 -152
  46. package/scripts/_safe_subprocess.py +0 -167
  47. package/scripts/_session_start_hook.py +0 -205
  48. package/scripts/_sor_gate_diff.py +0 -365
  49. package/scripts/_stdio_utf8.py +0 -59
  50. package/scripts/_triage_bootstrap_gitignore.py +0 -904
  51. package/scripts/_triage_classify_cli.py +0 -122
  52. package/scripts/_triage_queue_cli.py +0 -625
  53. package/scripts/_triage_scope_cli.py +0 -343
  54. package/scripts/_triage_scope_drift_cli.py +0 -121
  55. package/scripts/_triage_scope_ignores.py +0 -286
  56. package/scripts/_triage_scope_milestone.py +0 -432
  57. package/scripts/_triage_scope_mutations.py +0 -337
  58. package/scripts/_triage_scope_renderers.py +0 -207
  59. package/scripts/_triage_smoketest_stages.py +0 -674
  60. package/scripts/_triage_subscribe_cli.py +0 -140
  61. package/scripts/_triage_welcome_cli.py +0 -421
  62. package/scripts/_vbrief_build.py +0 -239
  63. package/scripts/_vbrief_fidelity.py +0 -479
  64. package/scripts/_vbrief_legacy.py +0 -589
  65. package/scripts/_vbrief_reconciliation.py +0 -883
  66. package/scripts/_vbrief_routing.py +0 -277
  67. package/scripts/_vbrief_safety.py +0 -778
  68. package/scripts/_vbrief_sources.py +0 -312
  69. package/scripts/_vbrief_speckit.py +0 -262
  70. package/scripts/_vbrief_story_quality.py +0 -353
  71. package/scripts/_vbrief_validation.py +0 -299
  72. package/scripts/build_dist.py +0 -412
  73. package/scripts/cache.py +0 -1078
  74. package/scripts/cache_scanner.py +0 -745
  75. package/scripts/candidates_log.py +0 -432
  76. package/scripts/capacity_backfill.py +0 -680
  77. package/scripts/capacity_show.py +0 -653
  78. package/scripts/ci_local.py +0 -689
  79. package/scripts/code_structure_validate.py +0 -765
  80. package/scripts/codebase_default_extractor.py +0 -495
  81. package/scripts/codebase_map.py +0 -304
  82. package/scripts/codebase_map_fresh.py +0 -104
  83. package/scripts/codebase_projection_registry.py +0 -94
  84. package/scripts/codebase_provider.py +0 -582
  85. package/scripts/doctor.py +0 -2552
  86. package/scripts/framework_commands.py +0 -505
  87. package/scripts/gh_rest.py +0 -882
  88. package/scripts/github_auth_modes.py +0 -437
  89. package/scripts/github_body.py +0 -292
  90. package/scripts/ip_risk.py +0 -531
  91. package/scripts/issue_emit.py +0 -670
  92. package/scripts/issue_ingest.py +0 -1064
  93. package/scripts/migrate_preflight.py +0 -418
  94. package/scripts/migrate_vbrief.py +0 -2677
  95. package/scripts/monitor_pr.py +0 -401
  96. package/scripts/pack_migrate_lessons.py +0 -336
  97. package/scripts/pack_migrate_patterns.py +0 -254
  98. package/scripts/pack_migrate_rules.py +0 -350
  99. package/scripts/pack_migrate_skills.py +0 -423
  100. package/scripts/pack_migrate_strategies.py +0 -311
  101. package/scripts/pack_migrate_swarm_spec.py +0 -250
  102. package/scripts/pack_render.py +0 -434
  103. package/scripts/packs_slice.py +0 -712
  104. package/scripts/platform_capabilities.py +0 -336
  105. package/scripts/policy.py +0 -2826
  106. package/scripts/policy_set.py +0 -324
  107. package/scripts/pr_check_closing_keywords.py +0 -524
  108. package/scripts/pr_check_protected_issues.py +0 -267
  109. package/scripts/pr_merge_readiness.py +0 -1004
  110. package/scripts/pr_wait_mergeable.py +0 -669
  111. package/scripts/prd_render.py +0 -159
  112. package/scripts/preflight_architecture_sor.py +0 -974
  113. package/scripts/preflight_branch.py +0 -289
  114. package/scripts/preflight_cache.py +0 -974
  115. package/scripts/preflight_gh.py +0 -721
  116. package/scripts/preflight_implementation.py +0 -272
  117. package/scripts/preflight_story_start.py +0 -838
  118. package/scripts/preflight_wip_cap.py +0 -149
  119. package/scripts/probe_session.py +0 -545
  120. package/scripts/project_render.py +0 -293
  121. package/scripts/quarantine_ext.py +0 -237
  122. package/scripts/reconcile_issues.py +0 -1442
  123. package/scripts/refresh-path.ps1 +0 -107
  124. package/scripts/release.py +0 -2030
  125. package/scripts/release_e2e.py +0 -1011
  126. package/scripts/release_publish.py +0 -486
  127. package/scripts/release_rollback.py +0 -980
  128. package/scripts/relocate.py +0 -1034
  129. package/scripts/resolve_changelog_unreleased.py +0 -667
  130. package/scripts/resolve_version.py +0 -490
  131. package/scripts/resume_conditions.py +0 -706
  132. package/scripts/ritual_sentinel.py +0 -609
  133. package/scripts/roadmap_render.py +0 -635
  134. package/scripts/rule_ownership_lint.py +0 -325
  135. package/scripts/scm.py +0 -591
  136. package/scripts/scope_audit_log.py +0 -387
  137. package/scripts/scope_decompose.py +0 -654
  138. package/scripts/scope_demote.py +0 -509
  139. package/scripts/scope_lifecycle.py +0 -1126
  140. package/scripts/scope_undo.py +0 -772
  141. package/scripts/session_start.py +0 -406
  142. package/scripts/setup_ghx.py +0 -339
  143. package/scripts/setup_windows.ps1 +0 -220
  144. package/scripts/slice_audit.py +0 -585
  145. package/scripts/slice_record.py +0 -530
  146. package/scripts/slice_record_existing.py +0 -692
  147. package/scripts/slug_normalize.py +0 -178
  148. package/scripts/spec_render.py +0 -477
  149. package/scripts/spec_validate.py +0 -238
  150. package/scripts/subagent_monitor.py +0 -658
  151. package/scripts/swarm_complete_cohort.py +0 -644
  152. package/scripts/swarm_launch.py +0 -1206
  153. package/scripts/swarm_readiness.py +0 -554
  154. package/scripts/swarm_verify_review_clean.py +0 -438
  155. package/scripts/swarm_worktrees.py +0 -497
  156. package/scripts/toolchain-check.py +0 -52
  157. package/scripts/triage_actions.py +0 -871
  158. package/scripts/triage_bootstrap.py +0 -1153
  159. package/scripts/triage_bulk.py +0 -630
  160. package/scripts/triage_classify.py +0 -932
  161. package/scripts/triage_help.py +0 -1685
  162. package/scripts/triage_queue.py +0 -1944
  163. package/scripts/triage_reconcile.py +0 -581
  164. package/scripts/triage_refresh.py +0 -643
  165. package/scripts/triage_scope.py +0 -999
  166. package/scripts/triage_scope_drift.py +0 -575
  167. package/scripts/triage_smoketest.py +0 -396
  168. package/scripts/triage_subscribe.py +0 -399
  169. package/scripts/triage_summary.py +0 -1011
  170. package/scripts/triage_welcome.py +0 -1178
  171. package/scripts/ts_check_lane.py +0 -86
  172. package/scripts/validate-links.py +0 -64
  173. package/scripts/validate_strategy_output.py +0 -212
  174. package/scripts/vbrief_activate.py +0 -228
  175. package/scripts/vbrief_migrate_conformance.py +0 -368
  176. package/scripts/vbrief_reconcile_graph.py +0 -306
  177. package/scripts/vbrief_reconcile_labels.py +0 -460
  178. package/scripts/vbrief_reconcile_umbrellas.py +0 -741
  179. package/scripts/vbrief_validate.py +0 -1144
  180. package/scripts/verify-stubs.py +0 -61
  181. package/scripts/verify_capacity.py +0 -160
  182. package/scripts/verify_encoding.py +0 -699
  183. package/scripts/verify_hooks_installed.py +0 -206
  184. package/scripts/verify_investigation.py +0 -360
  185. package/scripts/verify_judgment_gates.py +0 -827
  186. package/scripts/verify_no_task_runtime.py +0 -171
  187. package/scripts/verify_scm_boundary.py +0 -509
  188. package/scripts/verify_session_ritual.py +0 -389
  189. package/scripts/verify_tools.py +0 -426
  190. package/scripts/verify_vbrief_conformance.py +0 -478
@@ -1,239 +0,0 @@
1
- """Shared helpers for building scope vBRIEF dicts.
2
-
3
- Extracted from ``scripts/migrate_vbrief.py`` so ``scripts/issue_ingest.py`` (and
4
- any future ingestion / generation script) can reuse them without cross-importing
5
- the migrator. The canonical names are the public ``slugify`` / ``TODAY`` /
6
- ``create_scope_vbrief`` surface; ``migrate_vbrief.py`` continues to re-export
7
- the legacy underscore-prefixed aliases for backwards compatibility.
8
-
9
- Story: #454 (task issue:ingest).
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import copy
15
- import re
16
- from datetime import UTC, datetime
17
- from typing import Any
18
-
19
- # ----------------------------------------------------------------------------
20
- # Date helper
21
- # ----------------------------------------------------------------------------
22
-
23
- # Exposed for callers that want the canonical YYYY-MM-DD date used across
24
- # ingestion / migration filenames. Kept module-level so monkeypatching in tests
25
- # is straightforward.
26
- TODAY: str = datetime.now(UTC).strftime("%Y-%m-%d")
27
-
28
- # ----------------------------------------------------------------------------
29
- # Emitted vBRIEF version (#533)
30
- # ----------------------------------------------------------------------------
31
-
32
- # Canonical ``vBRIEFInfo.version`` string emitted on every scope vBRIEF built
33
- # via :func:`create_scope_vbrief`. Bumped from ``"0.5"`` to ``"0.6"`` as part
34
- # of the Agent 2 schema vendor transition (#533). During the transition the
35
- # validator accepts both strings; ingestion/generation paths only emit the
36
- # newer one.
37
- EMITTED_VBRIEF_VERSION: str = "0.6"
38
-
39
-
40
- # ----------------------------------------------------------------------------
41
- # Slugification
42
- # ----------------------------------------------------------------------------
43
-
44
-
45
- def slugify(text: str) -> str:
46
- """Convert a title to a filename-safe slug.
47
-
48
- - Lowercase, collapse whitespace/underscores to single hyphens
49
- - Drop characters that are not [a-z0-9-]
50
- - Trim to 60 characters maximum and strip leading/trailing hyphens
51
- """
52
- slug = text.lower().strip()
53
- # Preserve underscores through the strip pass so the next line can fold
54
- # them into hyphens (matches the documented contract).
55
- slug = re.sub(r"[^a-z0-9\s_-]", "", slug)
56
- slug = re.sub(r"[\s_]+", "-", slug)
57
- slug = re.sub(r"-+", "-", slug)
58
- return slug[:60].strip("-")
59
-
60
-
61
- # ----------------------------------------------------------------------------
62
- # Migrator provenance metadata namespace (#616)
63
- # ----------------------------------------------------------------------------
64
-
65
- # Per issue #616 (option A, scope-clamped), per-issue scope vBRIEFs emit
66
- # ``plan.narratives`` as an empty object because a ROADMAP.md row does not
67
- # carry enough data to populate any canonical narrative key meaningfully
68
- # (Goals / ProblemStatement / UserStories need hand-authoring). Migrator-
69
- # internal provenance (Phase, Tier, PhaseDescription plus reconciler-
70
- # emitted fields) is relocated under ``plan.metadata`` in the
71
- # ``x-migrator/*`` namespace so downstream readers can still access it
72
- # without it leaking into user-visible narratives.
73
- #
74
- # The surface key is a string (``"x-migrator"``) rather than a dotted
75
- # path because ``plan.metadata`` is the extension point for tool-specific
76
- # metadata. Using the ``x-migrator`` namespace signals "this value comes
77
- # from `task migrate:vbrief`" at a glance and keeps the payload compatible
78
- # with the vendored v0.6 schema without touching it.
79
- MIGRATOR_METADATA_KEY: str = "x-migrator"
80
-
81
- # ----------------------------------------------------------------------------
82
- # Reference provenance / trust helpers (#480)
83
- # ----------------------------------------------------------------------------
84
-
85
- INTERNAL_REFERENCE_TYPES = {"x-vbrief/plan", "x-vbrief/spec-section", "x-vbrief/user-request"}
86
- EXTERNAL_REFERENCE_TYPES = {
87
- "x-vbrief/github-issue",
88
- "x-vbrief/github-pr",
89
- "x-vbrief/jira-ticket",
90
- "x-vbrief/web-page",
91
- }
92
-
93
-
94
- def reference_with_default_trust(ref: dict[str, Any]) -> dict[str, Any]:
95
- """Return a copied reference with the default TrustLevel filled when known."""
96
- normalized = copy.deepcopy(ref)
97
- if "TrustLevel" in normalized:
98
- return normalized
99
- ref_type = normalized.get("type")
100
- if ref_type in INTERNAL_REFERENCE_TYPES:
101
- normalized["TrustLevel"] = "internal"
102
- elif ref_type in EXTERNAL_REFERENCE_TYPES:
103
- normalized["TrustLevel"] = "external"
104
- return normalized
105
-
106
-
107
- def _github_issue_reference(
108
- *, repo_url: str, number: Any, title: Any
109
- ) -> dict[str, str] | None:
110
- cleaned_repo = str(repo_url or "").strip().rstrip("/")
111
- cleaned_number = str(number or "").strip().lstrip("#").strip()
112
- if not cleaned_repo or not cleaned_number:
113
- return None
114
- cleaned_title = str(title or "").strip()
115
- ref_title = (
116
- f"Issue #{cleaned_number}: {cleaned_title}"
117
- if cleaned_title and cleaned_title != "Untitled"
118
- else f"Issue #{cleaned_number}"
119
- )
120
- return {
121
- "uri": f"{cleaned_repo}/issues/{cleaned_number}",
122
- "type": "x-vbrief/github-issue",
123
- "title": ref_title,
124
- }
125
-
126
-
127
- def _reference_has_required_fields(ref: dict[str, Any] | None) -> bool:
128
- if ref is None:
129
- return False
130
- for key in ("uri", "type"):
131
- value = ref.get(key)
132
- if not isinstance(value, str) or not value.strip():
133
- return False
134
- return True
135
-
136
-
137
- # ----------------------------------------------------------------------------
138
- # Scope vBRIEF construction
139
- # ----------------------------------------------------------------------------
140
-
141
-
142
- def create_scope_vbrief(
143
- item: dict,
144
- repo_url: str = "",
145
- status: str = "pending",
146
- phase_description: str = "",
147
- ) -> dict:
148
- """Build a scope vBRIEF dict for a roadmap or issue item.
149
-
150
- ``item`` is a generic dict with the following recognised keys:
151
- - ``number`` (str): GitHub issue number (without '#')
152
- - ``title`` (str): scope title (required in practice)
153
- - ``phase`` (str): roadmap phase label (optional)
154
- - ``tier`` (str): sub-phase tier label (optional)
155
-
156
- The returned structure conforms to the canonical vBRIEF version emitted
157
- by deft (``EMITTED_VBRIEF_VERSION``, currently ``"0.6"`` per #533):
158
- - ``vBRIEFInfo.version = EMITTED_VBRIEF_VERSION``
159
- - ``plan.title`` is ``item['title']`` verbatim
160
- - ``plan.status`` is ``status`` (default ``pending``)
161
- - ``plan.narratives`` is ``{}`` (empty). Per-issue scope vBRIEFs
162
- intentionally ship with no narratives -- ROADMAP rows do not
163
- carry enough data for any canonical narrative key, and inventing
164
- keys leaked migrator internals into user-visible narratives
165
- (#616). Migrator-internal provenance (``Phase`` / ``Tier`` /
166
- ``PhaseDescription``) lives in ``plan.metadata['x-migrator']``
167
- when populated.
168
- - ``plan.references`` carries the canonical v0.6 origin-provenance
169
- entry ``{uri, type: "x-vbrief/github-issue", title}`` when
170
- ``item['number']`` is non-empty AND ``repo_url`` can be resolved
171
- to a GitHub owner/repo (#613). Legacy readers that used to
172
- receive a bare ``{type: "github-issue", id: "#N"}`` must migrate
173
- to the canonical shape -- see ``scripts/reconcile_issues.py``
174
- for a bilingual reader example.
175
- """
176
- number = str(item.get("number", "") or "").strip().lstrip("#").strip()
177
- title = str(item.get("title", "Untitled") or "Untitled").strip() or "Untitled"
178
- phase = item.get("phase", "")
179
- tier = item.get("tier", "")
180
-
181
- desc_label = f"#{number}: {title}" if number else title
182
-
183
- vbrief: dict = {
184
- "vBRIEFInfo": {
185
- "version": EMITTED_VBRIEF_VERSION,
186
- "description": f"Scope vBRIEF for {desc_label}",
187
- },
188
- "plan": {
189
- "title": title,
190
- "status": status,
191
- "narratives": {},
192
- "items": [],
193
- },
194
- }
195
-
196
- # #616: relocate migrator-internal provenance from plan.narratives to
197
- # plan.metadata['x-migrator'] so downstream tools (roadmap_render) keep
198
- # working without leaking invented keys into user-visible narratives.
199
- migrator_meta: dict[str, str] = {}
200
- if phase:
201
- migrator_meta["Phase"] = phase
202
- if tier:
203
- migrator_meta["Tier"] = tier
204
- if phase_description:
205
- migrator_meta["PhaseDescription"] = phase_description
206
- if migrator_meta:
207
- vbrief["plan"].setdefault("metadata", {})[MIGRATOR_METADATA_KEY] = migrator_meta
208
-
209
- # #613: origin provenance per RFC #309 D11 + conventions/references.md.
210
- # Canonical shape: {uri, type: "x-vbrief/github-issue", title}. A
211
- # reference is only emitted when BOTH ``number`` and ``repo_url`` are
212
- # present -- the schema's VBriefReference definition requires ``uri``
213
- # so we cannot honestly emit a reference without a resolvable URL.
214
- # ROADMAP bare-text rows (no issue number) legitimately ship with no
215
- # origin reference; the migrator logs them as proposed/ orphans.
216
- canonical_ref = _github_issue_reference(
217
- repo_url=repo_url,
218
- number=number,
219
- title=title,
220
- )
221
- trusted_ref = (
222
- reference_with_default_trust(canonical_ref)
223
- if _reference_has_required_fields(canonical_ref)
224
- else None
225
- )
226
- if trusted_ref is not None and _reference_has_required_fields(trusted_ref):
227
- vbrief["plan"]["references"] = [trusted_ref]
228
-
229
- return vbrief
230
-
231
-
232
- __all__ = [
233
- "EMITTED_VBRIEF_VERSION",
234
- "MIGRATOR_METADATA_KEY",
235
- "TODAY",
236
- "reference_with_default_trust",
237
- "slugify",
238
- "create_scope_vbrief",
239
- ]