@deftai/directive-content 0.55.2 → 0.56.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 (217) hide show
  1. package/.githooks/pre-commit +143 -0
  2. package/.githooks/pre-push +121 -0
  3. package/QUICK-START.md +2 -2
  4. package/Taskfile.yml +934 -0
  5. package/UPGRADING.md +47 -1
  6. package/events/README.md +3 -3
  7. package/package.json +5 -4
  8. package/scripts/_agents_md.py +494 -0
  9. package/scripts/_cache_fetch.py +635 -0
  10. package/scripts/_cache_quota.py +529 -0
  11. package/scripts/_cache_refresh.py +163 -0
  12. package/scripts/_cache_validate.py +209 -0
  13. package/scripts/_content_root.py +42 -0
  14. package/scripts/_doctor_state.py +277 -0
  15. package/scripts/_event_detect.py +305 -0
  16. package/scripts/_events.py +514 -0
  17. package/scripts/_lifecycle_hygiene.py +568 -0
  18. package/scripts/_pathspec.py +91 -0
  19. package/scripts/_policy_show_cli.py +266 -0
  20. package/scripts/_precutover.py +92 -0
  21. package/scripts/_project_context.py +224 -0
  22. package/scripts/_project_definition_io.py +164 -0
  23. package/scripts/_relocate_snapshot.py +209 -0
  24. package/scripts/_relocate_states.py +343 -0
  25. package/scripts/_resolve_preflight_path.py +152 -0
  26. package/scripts/_safe_subprocess.py +167 -0
  27. package/scripts/_session_start_hook.py +205 -0
  28. package/scripts/_sor_gate_diff.py +365 -0
  29. package/scripts/_stdio_utf8.py +59 -0
  30. package/scripts/_triage_bootstrap_gitignore.py +904 -0
  31. package/scripts/_triage_classify_cli.py +122 -0
  32. package/scripts/_triage_queue_cli.py +625 -0
  33. package/scripts/_triage_scope_cli.py +343 -0
  34. package/scripts/_triage_scope_drift_cli.py +121 -0
  35. package/scripts/_triage_scope_ignores.py +286 -0
  36. package/scripts/_triage_scope_milestone.py +432 -0
  37. package/scripts/_triage_scope_mutations.py +337 -0
  38. package/scripts/_triage_scope_renderers.py +207 -0
  39. package/scripts/_triage_smoketest_stages.py +674 -0
  40. package/scripts/_triage_subscribe_cli.py +140 -0
  41. package/scripts/_triage_welcome_cli.py +421 -0
  42. package/scripts/_vbrief_build.py +239 -0
  43. package/scripts/_vbrief_fidelity.py +479 -0
  44. package/scripts/_vbrief_legacy.py +589 -0
  45. package/scripts/_vbrief_reconciliation.py +883 -0
  46. package/scripts/_vbrief_routing.py +277 -0
  47. package/scripts/_vbrief_safety.py +778 -0
  48. package/scripts/_vbrief_sources.py +312 -0
  49. package/scripts/_vbrief_speckit.py +262 -0
  50. package/scripts/_vbrief_story_quality.py +353 -0
  51. package/scripts/_vbrief_validation.py +299 -0
  52. package/scripts/build_dist.py +412 -0
  53. package/scripts/cache.py +1078 -0
  54. package/scripts/cache_scanner.py +745 -0
  55. package/scripts/candidates_log.py +432 -0
  56. package/scripts/capacity_backfill.py +680 -0
  57. package/scripts/capacity_show.py +653 -0
  58. package/scripts/ci_local.py +689 -0
  59. package/scripts/code_structure_validate.py +765 -0
  60. package/scripts/codebase_default_extractor.py +495 -0
  61. package/scripts/codebase_map.py +304 -0
  62. package/scripts/codebase_map_fresh.py +104 -0
  63. package/scripts/codebase_projection_registry.py +94 -0
  64. package/scripts/codebase_provider.py +582 -0
  65. package/scripts/doctor.py +2257 -0
  66. package/scripts/framework_commands.py +505 -0
  67. package/scripts/gh_rest.py +882 -0
  68. package/scripts/github_auth_modes.py +437 -0
  69. package/scripts/github_body.py +292 -0
  70. package/scripts/ip_risk.py +531 -0
  71. package/scripts/issue_emit.py +670 -0
  72. package/scripts/issue_ingest.py +1064 -0
  73. package/scripts/migrate_preflight.py +418 -0
  74. package/scripts/migrate_vbrief.py +2677 -0
  75. package/scripts/monitor_pr.py +401 -0
  76. package/scripts/pack_migrate_lessons.py +336 -0
  77. package/scripts/pack_migrate_patterns.py +254 -0
  78. package/scripts/pack_migrate_rules.py +350 -0
  79. package/scripts/pack_migrate_skills.py +423 -0
  80. package/scripts/pack_migrate_strategies.py +311 -0
  81. package/scripts/pack_migrate_swarm_spec.py +250 -0
  82. package/scripts/pack_render.py +434 -0
  83. package/scripts/packs_slice.py +712 -0
  84. package/scripts/platform_capabilities.py +336 -0
  85. package/scripts/policy.py +2826 -0
  86. package/scripts/policy_set.py +324 -0
  87. package/scripts/pr_check_closing_keywords.py +524 -0
  88. package/scripts/pr_check_protected_issues.py +267 -0
  89. package/scripts/pr_merge_readiness.py +1004 -0
  90. package/scripts/pr_wait_mergeable.py +669 -0
  91. package/scripts/prd_render.py +159 -0
  92. package/scripts/preflight_architecture_sor.py +974 -0
  93. package/scripts/preflight_branch.py +289 -0
  94. package/scripts/preflight_cache.py +974 -0
  95. package/scripts/preflight_gh.py +721 -0
  96. package/scripts/preflight_implementation.py +272 -0
  97. package/scripts/preflight_story_start.py +838 -0
  98. package/scripts/preflight_wip_cap.py +149 -0
  99. package/scripts/probe_session.py +545 -0
  100. package/scripts/project_render.py +293 -0
  101. package/scripts/quarantine_ext.py +237 -0
  102. package/scripts/reconcile_issues.py +1442 -0
  103. package/scripts/refresh-path.ps1 +107 -0
  104. package/scripts/release.py +2030 -0
  105. package/scripts/release_e2e.py +1011 -0
  106. package/scripts/release_publish.py +486 -0
  107. package/scripts/release_rollback.py +980 -0
  108. package/scripts/relocate.py +1034 -0
  109. package/scripts/resolve_changelog_unreleased.py +667 -0
  110. package/scripts/resolve_version.py +490 -0
  111. package/scripts/resume_conditions.py +706 -0
  112. package/scripts/ritual_sentinel.py +609 -0
  113. package/scripts/roadmap_render.py +635 -0
  114. package/scripts/rule_ownership_lint.py +325 -0
  115. package/scripts/scm.py +591 -0
  116. package/scripts/scope_audit_log.py +387 -0
  117. package/scripts/scope_decompose.py +654 -0
  118. package/scripts/scope_demote.py +509 -0
  119. package/scripts/scope_lifecycle.py +1126 -0
  120. package/scripts/scope_undo.py +772 -0
  121. package/scripts/session_start.py +406 -0
  122. package/scripts/setup_ghx.py +339 -0
  123. package/scripts/setup_windows.ps1 +220 -0
  124. package/scripts/slice_audit.py +585 -0
  125. package/scripts/slice_record.py +530 -0
  126. package/scripts/slice_record_existing.py +692 -0
  127. package/scripts/slug_normalize.py +178 -0
  128. package/scripts/spec_render.py +477 -0
  129. package/scripts/spec_validate.py +238 -0
  130. package/scripts/subagent_monitor.py +658 -0
  131. package/scripts/swarm_complete_cohort.py +644 -0
  132. package/scripts/swarm_launch.py +1206 -0
  133. package/scripts/swarm_readiness.py +554 -0
  134. package/scripts/swarm_verify_review_clean.py +438 -0
  135. package/scripts/swarm_worktrees.py +497 -0
  136. package/scripts/toolchain-check.py +52 -0
  137. package/scripts/triage_actions.py +871 -0
  138. package/scripts/triage_bootstrap.py +1153 -0
  139. package/scripts/triage_bulk.py +630 -0
  140. package/scripts/triage_classify.py +932 -0
  141. package/scripts/triage_help.py +1685 -0
  142. package/scripts/triage_queue.py +1944 -0
  143. package/scripts/triage_reconcile.py +581 -0
  144. package/scripts/triage_refresh.py +643 -0
  145. package/scripts/triage_scope.py +999 -0
  146. package/scripts/triage_scope_drift.py +575 -0
  147. package/scripts/triage_smoketest.py +396 -0
  148. package/scripts/triage_subscribe.py +399 -0
  149. package/scripts/triage_summary.py +1011 -0
  150. package/scripts/triage_welcome.py +1178 -0
  151. package/scripts/ts_check_lane.py +86 -0
  152. package/scripts/validate-links.py +64 -0
  153. package/scripts/validate_strategy_output.py +212 -0
  154. package/scripts/vbrief_activate.py +228 -0
  155. package/scripts/vbrief_migrate_conformance.py +368 -0
  156. package/scripts/vbrief_reconcile_graph.py +306 -0
  157. package/scripts/vbrief_reconcile_labels.py +460 -0
  158. package/scripts/vbrief_reconcile_umbrellas.py +741 -0
  159. package/scripts/vbrief_validate.py +1195 -0
  160. package/scripts/verify-stubs.py +61 -0
  161. package/scripts/verify_capacity.py +160 -0
  162. package/scripts/verify_encoding.py +699 -0
  163. package/scripts/verify_hooks_installed.py +206 -0
  164. package/scripts/verify_investigation.py +360 -0
  165. package/scripts/verify_judgment_gates.py +827 -0
  166. package/scripts/verify_no_task_runtime.py +171 -0
  167. package/scripts/verify_scm_boundary.py +509 -0
  168. package/scripts/verify_session_ritual.py +389 -0
  169. package/scripts/verify_tools.py +426 -0
  170. package/scripts/verify_vbrief_conformance.py +478 -0
  171. package/tasks/architecture.yml +13 -0
  172. package/tasks/cache.yml +69 -0
  173. package/tasks/capacity.yml +38 -0
  174. package/tasks/change.yml +46 -0
  175. package/tasks/changelog.yml +24 -0
  176. package/tasks/ci.yml +49 -0
  177. package/tasks/codebase.yml +47 -0
  178. package/tasks/commit.yml +30 -0
  179. package/tasks/core.yml +126 -0
  180. package/tasks/deployments.yml +54 -0
  181. package/tasks/framework.yml +74 -0
  182. package/tasks/install.yml +60 -0
  183. package/tasks/issue.yml +50 -0
  184. package/tasks/migrate.yml +73 -0
  185. package/tasks/packs.yml +92 -0
  186. package/tasks/policy.yml +75 -0
  187. package/tasks/pr.yml +89 -0
  188. package/tasks/prd.yml +39 -0
  189. package/tasks/project.yml +27 -0
  190. package/tasks/reconcile.yml +32 -0
  191. package/tasks/relocate.yml +56 -0
  192. package/tasks/roadmap.yml +28 -0
  193. package/tasks/scm.yml +126 -0
  194. package/tasks/scope-undo.yml +36 -0
  195. package/tasks/scope.yml +141 -0
  196. package/tasks/session.yml +19 -0
  197. package/tasks/setup.yml +37 -0
  198. package/tasks/slice.yml +69 -0
  199. package/tasks/spec.yml +41 -0
  200. package/tasks/swarm.yml +85 -0
  201. package/tasks/toolchain.yml +13 -0
  202. package/tasks/triage-actions.yml +94 -0
  203. package/tasks/triage-bootstrap.yml +43 -0
  204. package/tasks/triage-bulk.yml +75 -0
  205. package/tasks/triage-classify.yml +30 -0
  206. package/tasks/triage-queue.yml +50 -0
  207. package/tasks/triage-reconcile.yml +29 -0
  208. package/tasks/triage-scope-drift.yml +29 -0
  209. package/tasks/triage-scope.yml +31 -0
  210. package/tasks/triage-smoketest.yml +33 -0
  211. package/tasks/triage-subscribe.yml +36 -0
  212. package/tasks/triage-summary.yml +29 -0
  213. package/tasks/triage-welcome.yml +32 -0
  214. package/tasks/ts.yml +328 -0
  215. package/tasks/vbrief.yml +206 -0
  216. package/tasks/verify.yml +292 -0
  217. package/templates/agents-entry.md +1 -1
package/Taskfile.yml ADDED
@@ -0,0 +1,934 @@
1
+ version: '3'
2
+
3
+ vars:
4
+ PROJECT_NAME: deft
5
+ # VERSION is resolved dynamically (#723) so `task build` produces
6
+ # `dist/deft-{version}.{zip,tar.gz}` matching the in-flight release.
7
+ # Resolution priority (mirrors scripts/resolve_version.py):
8
+ # 1. $DEFT_RELEASE_VERSION env var (set by scripts/release.py:run_build
9
+ # so `task release -- 0.21.0` builds dist/deft-0.21.0.zip).
10
+ # 2. `git describe --tags --abbrev=0` stripped of leading `v`.
11
+ # 3. `0.0.0-dev` fallback for fresh checkouts with no tags.
12
+ # The previous hard-coded literal (`VERSION: 0.20.0`) was the root cause
13
+ # of #723: every release after v0.20.0 produced a stale artifact name
14
+ # because nothing in the release pipeline updated the Taskfile literal.
15
+ # Inline POSIX sh (run by go-task's embedded mvdan/sh interpreter so the
16
+ # block is cross-platform on Windows / macOS / Linux without requiring
17
+ # uv/python at parse time -- the Python equivalent lives in
18
+ # scripts/resolve_version.py for Python callers + regression tests).
19
+ VERSION:
20
+ sh: |
21
+ if [ -n "$DEFT_RELEASE_VERSION" ]; then
22
+ printf '%s' "$DEFT_RELEASE_VERSION"
23
+ elif tag=$(git describe --tags --abbrev=0 2>/dev/null); then
24
+ printf '%s' "${tag#v}"
25
+ else
26
+ printf '0.0.0-dev'
27
+ fi
28
+ # Each included sub-taskfile (tasks/*.yml) defines its own DEFT_ROOT as
29
+ # `{{joinPath .TASKFILE_DIR ".."}}` so scripts can be dispatched via
30
+ # `{{.DEFT_ROOT}}/scripts/...` on every platform (#566). `joinPath` is
31
+ # evaluated eagerly by go-task's templating and uses Go's `filepath.Clean`,
32
+ # which yields a native-separator, `..`-free absolute path that
33
+ # `uv run python` can open on Windows. The previous
34
+ # `{{.TASKFILE_DIR}}/../scripts/...` shape mixed native separators with
35
+ # forward-slash traversal and normalized incorrectly under Windows Python,
36
+ # dropping the deft/ prefix.
37
+ #
38
+ # DEFT_ROOT is intentionally NOT defined here at the root Taskfile level
39
+ # because go-task re-evaluates var templates at use site in included
40
+ # subfiles -- a root-level `DEFT_ROOT: '{{.TASKFILE_DIR}}'` would expand
41
+ # to the subfile's own directory (tasks/) when referenced from a subfile,
42
+ # not to the deft/ root.
43
+
44
+ # Top-level env propagates into included taskfiles (Task v3 includes inherit
45
+ # the parent env:). PYTHONUTF8=1 ensures Python scripts invoked from any
46
+ # deft task have UTF-8 stdout/stderr on Windows (cp1252 default would crash
47
+ # on the ✓/→/✗/⚠ symbols emitted by spec_validate / roadmap_render / etc.).
48
+ # Every task that runs Python ALSO sets this in its own env: block as a
49
+ # belt-and-suspenders guard -- see #540 for the full audit.
50
+ #
51
+ # UV_PROJECT is the Layer-1 safety net for #1011: every framework-side
52
+ # `uv run` invocation must resolve against the framework's own pyproject.toml,
53
+ # not an ancestor pyproject.toml that happens to live above the install
54
+ # location on the consumer machine. Without this, `uv run` walks upward
55
+ # from cwd looking for the nearest pyproject.toml and binds to whatever
56
+ # it finds first -- on a typical dev box with a parent workspace
57
+ # pyproject.toml, that workspace's build backend (e.g. unresolvable
58
+ # `setuptools.backends._legacy:_Backend`) crashes during environment
59
+ # resolution before any framework task body runs. UV_PROJECT short-circuits
60
+ # the upward walk by pinning the project root explicitly. {{.TASKFILE_DIR}}
61
+ # at this top-level env: resolves to the directory containing this
62
+ # Taskfile.yml (the framework root), which is exactly the right pin for
63
+ # the framework's own pyproject.toml. CLI `--project` on each call site
64
+ # (Layer 2, see tasks/*.yml) overrides env, which overrides walk -- the
65
+ # CLI flag is the contract; UV_PROJECT is defense-in-depth for any task
66
+ # that drops the flag in a future edit. See #1011 for the full root-cause
67
+ # analysis and the two-layer rationale.
68
+ env:
69
+ PYTHONUTF8: "1"
70
+ UV_PROJECT: '{{.TASKFILE_DIR}}'
71
+
72
+ includes:
73
+ core:
74
+ taskfile: ./tasks/core.yml
75
+ optional: true
76
+ ts:
77
+ taskfile: ./tasks/ts.yml
78
+ optional: true
79
+ spec:
80
+ taskfile: ./tasks/spec.yml
81
+ optional: true
82
+ install:
83
+ taskfile: ./tasks/install.yml
84
+ optional: true
85
+ deployments:
86
+ taskfile: ./tasks/deployments.yml
87
+ optional: true
88
+ toolchain:
89
+ taskfile: ./tasks/toolchain.yml
90
+ optional: true
91
+ verify:
92
+ taskfile: ./tasks/verify.yml
93
+ optional: true
94
+ architecture:
95
+ taskfile: ./tasks/architecture.yml
96
+ optional: true
97
+ codebase:
98
+ taskfile: ./tasks/codebase.yml
99
+ optional: true
100
+ change:
101
+ taskfile: ./tasks/change.yml
102
+ optional: true
103
+ commit:
104
+ taskfile: ./tasks/commit.yml
105
+ optional: true
106
+ scope:
107
+ taskfile: ./tasks/scope.yml
108
+ optional: true
109
+ # D15 (#1134): scope:undo audit-log reversibility verb. Standalone
110
+ # fragment per the post-D12 sub-task convention so the cross-child
111
+ # coordination contract on tasks/scope.yml does not collide. Inner
112
+ # task `undo` is exposed as the user-facing alias `task scope:undo`
113
+ # below.
114
+ scope-undo:
115
+ taskfile: ./tasks/scope-undo.yml
116
+ optional: true
117
+ swarm:
118
+ taskfile: ./tasks/swarm.yml
119
+ optional: false
120
+ roadmap:
121
+ taskfile: ./tasks/roadmap.yml
122
+ optional: true
123
+ project:
124
+ taskfile: ./tasks/project.yml
125
+ optional: true
126
+ migrate:
127
+ taskfile: ./tasks/migrate.yml
128
+ optional: true
129
+ vbrief:
130
+ taskfile: ./tasks/vbrief.yml
131
+ optional: true
132
+ prd:
133
+ taskfile: ./tasks/prd.yml
134
+ optional: true
135
+ reconcile:
136
+ taskfile: ./tasks/reconcile.yml
137
+ optional: true
138
+ issue:
139
+ taskfile: ./tasks/issue.yml
140
+ optional: true
141
+ pr:
142
+ taskfile: ./tasks/pr.yml
143
+ optional: true
144
+ ci:
145
+ taskfile: ./tasks/ci.yml
146
+ optional: true
147
+ policy:
148
+ taskfile: ./tasks/policy.yml
149
+ optional: true
150
+ framework:
151
+ taskfile: ./tasks/framework.yml
152
+ optional: true
153
+ session:
154
+ taskfile: ./tasks/session.yml
155
+ optional: true
156
+ # #883 Story 1 stub include. The fragment exposes its inner tasks
157
+ # (`issue:list` / `issue:view` / `issue:close` / `issue:edit`) under the
158
+ # `scm` namespace key, producing the canonical `scm:issue:*` surface in
159
+ # `task -l` with no doubled prefix. Forward-compat marker block lives at
160
+ # the top of `tasks/scm.yml`; the full scm:* namespace lives at #881 and
161
+ # replaces this stub wholesale when it lands.
162
+ scm:
163
+ taskfile: ./tasks/scm.yml
164
+ optional: true
165
+ # #883 Story 2 cache + quarantine layer. Five-command surface
166
+ # (cache:put / cache:get / cache:invalidate / cache:fetch-all /
167
+ # cache:prune) under the canonical `cache:` namespace via the include
168
+ # key. Forward-compat: future v2 cache surfaces (cache:check /
169
+ # cache:refresh / cache:doctor / cache:stats / quarantine:scan) are
170
+ # deferred per the epic deferred_to_v2 list and land here when v2
171
+ # ships.
172
+ cache:
173
+ taskfile: ./tasks/cache.yml
174
+ optional: true
175
+ # Triage v1 fragment includes (#845 epic, #883 Story 3 rebind onto cache:*).
176
+ #
177
+ # Three standalone fragments authored by stories A3, A4, and A6
178
+ # respectively (the legacy A1 `triage-cache` fragment was deleted in
179
+ # #883 Story 3 -- the unified `cache:*` surface above is the
180
+ # single content-mirroring layer). Each fragment is `optional: true`
181
+ # so the parent Taskfile parses cleanly even when a sibling fragment
182
+ # has not yet landed.
183
+ #
184
+ # Namespacing: go-task v3 prefixes inner task names with the include
185
+ # key. Two includes cannot share a single namespace key, so the
186
+ # fragments use unique keys derived from the file basename. The
187
+ # user-facing `task triage:bootstrap` / `task triage:accept` /
188
+ # `task triage:bulk-*` etc. forms are exposed via top-level alias
189
+ # tasks below.
190
+ triage-actions:
191
+ taskfile: ./tasks/triage-actions.yml
192
+ optional: true
193
+ triage-bulk:
194
+ taskfile: ./tasks/triage-bulk.yml
195
+ optional: true
196
+ triage-bootstrap:
197
+ taskfile: ./tasks/triage-bootstrap.yml
198
+ optional: true
199
+ # #1468: `task triage:reconcile` audit-log self-heal. Inner task
200
+ # `reconcile` is exposed as the user-facing alias `task triage:reconcile`
201
+ # in the alias block below.
202
+ triage-reconcile:
203
+ taskfile: ./tasks/triage-reconcile.yml
204
+ optional: true
205
+ # D12 (#1131): typed plan.policy.triageScope[] subscription surface.
206
+ # Inner task `scope` is exposed as the user-facing alias `task triage:scope`
207
+ # in the alias block below.
208
+ triage-scope:
209
+ taskfile: ./tasks/triage-scope.yml
210
+ optional: true
211
+ # D14 (#1133): subscription drift detector. Inner task `scope-drift` is
212
+ # exposed as the user-facing alias `task triage:scope-drift` in the
213
+ # alias block below.
214
+ triage-scope-drift:
215
+ taskfile: ./tasks/triage-scope-drift.yml
216
+ optional: true
217
+ # D14 (#1133): subscribe / unsubscribe mutation verbs. Inner tasks
218
+ # `subscribe` / `unsubscribe` are exposed as the user-facing aliases
219
+ # `task triage:subscribe` / `task triage:unsubscribe` below.
220
+ triage-subscribe:
221
+ taskfile: ./tasks/triage-subscribe.yml
222
+ optional: true
223
+ # D10 (#1129): auto-classification surface. Inner task `classify` is
224
+ # exposed as the user-facing alias `task triage:classify` in the alias
225
+ # block below.
226
+ triage-classify:
227
+ taskfile: ./tasks/triage-classify.yml
228
+ optional: true
229
+ # D2 (#1122): `task triage:summary` one-liner -- status surface invoked by
230
+ # the session-start ritual (N9 / #1149). Inner task `summary` is exposed
231
+ # as the user-facing alias `task triage:summary` in the alias block below.
232
+ triage-summary:
233
+ taskfile: ./tasks/triage-summary.yml
234
+ optional: true
235
+ # D11 (#1128): ranked queue + per-item show + audit-log triage surfaces.
236
+ # Inner tasks queue/show/audit are exposed as the user-facing aliases
237
+ # `task triage:queue` / `task triage:show` / `task triage:audit` below.
238
+ triage-queue:
239
+ taskfile: ./tasks/triage-queue.yml
240
+ optional: true
241
+ # N3 (#1143): `task triage:welcome` 6-phase onboarding ritual. Inner
242
+ # task `welcome` is exposed as the user-facing alias `task triage:welcome`
243
+ # in the alias block below.
244
+ triage-welcome:
245
+ taskfile: ./tasks/triage-welcome.yml
246
+ optional: true
247
+ # N6 (#1146): `task triage:smoketest` end-to-end synthetic test of the
248
+ # cache-as-operator-working-set surface. Inner task `smoketest` is
249
+ # exposed as the user-facing alias `task triage:smoketest` in the
250
+ # alias block below.
251
+ triage-smoketest:
252
+ taskfile: ./tasks/triage-smoketest.yml
253
+ optional: true
254
+ # Windows maintainer onboarding fragment (#902). Exposes the inner task
255
+ # `toolchain` as `task setup:toolchain`. Note: the root-level `setup` task
256
+ # below (git-hooks bootstrap) coexists with `setup:toolchain` because
257
+ # go-task treats them as distinct task names.
258
+ setup:
259
+ taskfile: ./tasks/setup.yml
260
+ optional: true
261
+ # CHANGELOG.md union-merge helper (#911). Exposes
262
+ # `task changelog:resolve-unreleased` -- the canonical swarm-cascade Phase 6
263
+ # Step 1 surface that replaces the older HEAD-take-and-discard pattern that
264
+ # silently dropped rebasing-branch CHANGELOG entries on every cascade rebase.
265
+ # See skills/deft-directive-swarm/SKILL.md Phase 6 Step 1 for the manual-
266
+ # fallback contract; the include is `optional: true` so the parent Taskfile
267
+ # parses cleanly when the fragment is absent (rolling-merge tolerance).
268
+ changelog:
269
+ taskfile: ./tasks/changelog.yml
270
+ optional: true
271
+ # Wipe-and-reinstall relocator (#992 PR2). Exposes `task relocate` --
272
+ # forwards user-facing flags (`--confirm` / `--dry-run` / `--force` /
273
+ # `--rollback` / `--no-snapshot` / `--json` / `--quiet`) via
274
+ # {{.CLI_ARGS}}; per `conventions/task-caching.md` no `sources:` /
275
+ # `generates:` so the recovery flags reach the script (#574). The
276
+ # include is `optional: true` for rolling-merge tolerance.
277
+ relocate:
278
+ taskfile: ./tasks/relocate.yml
279
+ optional: true
280
+ # N7 (#1147): slice:* fragment exposing `task slice:record-existing`
281
+ # (retrofit slices.jsonl for hand-filed cohorts) + `task slice:list`
282
+ # (read surface). Include key `slice-record` (not `slice`) so the
283
+ # fragment-namespace forms (`slice-record:record-existing`,
284
+ # `slice-record:list`) do NOT collide with the user-facing
285
+ # `slice:record-existing` / `slice:list` aliases defined below.
286
+ # Inner tasks are `internal: true`; aliases at the root surface the
287
+ # documented user-facing names per the established triage:* / scope:*
288
+ # convention.
289
+ slice-record:
290
+ taskfile: ./tasks/slice.yml
291
+ optional: true
292
+ # Capacity allocation accounting surface (#1419 Delivery Slice 4). Exposes
293
+ # `task capacity:show` (advisory, offline target-vs-actual bucket mix). The
294
+ # companion `task verify:capacity` lives in tasks/verify.yml and is
295
+ # DELIBERATELY absent from the `task check` aggregate -- capacity is
296
+ # advise-by-default and must never fail-closed on the framework tree.
297
+ # `optional: true` for rolling-merge tolerance.
298
+ capacity:
299
+ taskfile: ./tasks/capacity.yml
300
+ optional: true
301
+ # Pack-slicing surface (#1283 design, #1294 pilot, ADR-001 Layer B). Exposes
302
+ # `task packs:slice` (named-slice API), `task packs:render` (regenerate the
303
+ # meta/lessons.md projection), and `task packs:verify-drift` (the drift gate,
304
+ # also surfaced as the user-facing alias `task verify:pack-drift` below and
305
+ # wired into `check:framework-source`). `optional: true` for rolling-merge
306
+ # tolerance.
307
+ packs:
308
+ taskfile: ./tasks/packs.yml
309
+ optional: true
310
+
311
+ tasks:
312
+ default:
313
+ desc: List all available tasks
314
+ cmds:
315
+ - task --list
316
+ silent: true
317
+
318
+ # Backward-compatible aliases -- project convention is `task check`, `task test`, etc.
319
+ check:
320
+ desc: "Run the context-appropriate pre-commit gate: full framework self-check in this repo, consumer-safe gate from vendored installs (#1519)."
321
+ dir: '{{.USER_WORKING_DIR}}'
322
+ deps:
323
+ - task: verify:_ts-build
324
+ cmds:
325
+ # Oracle/fallback (parity): scripts/_project_context.py --dispatch-task-check (#1854 s5).
326
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" check --framework-root "{{.TASKFILE_DIR}}" --project-root "{{.USER_WORKING_DIR}}"
327
+
328
+ check:framework-source:
329
+ desc: "Run all framework source-repo pre-commit checks explicitly (skips @pytest.mark.slow tests via pyproject addopts -- run `task check:slow` for the slow lane, #975)."
330
+ deps:
331
+ - core:validate
332
+ - core:lint
333
+ - core:test
334
+ - ts:check-lane
335
+ - toolchain:check
336
+ - verify:stubs
337
+ - verify:links
338
+ - verify:rule-ownership
339
+ - verify:content-manifest
340
+ - verify:go-freeze
341
+ - verify:bridge-drift
342
+ - verify:branch
343
+ - verify:encoding
344
+ - verify:vbrief-conformance
345
+ - verify:destructive-gh-verbs
346
+ - verify:scm-boundary
347
+ - verify:no-task-runtime
348
+ - verify:cache-fresh
349
+ - verify:pack-drift
350
+ - verify-wip-cap-framework-self-check
351
+ - vbrief:validate
352
+ - codebase:validate-structure
353
+ - verify:codebase-map-fresh
354
+ - verify-strategy-output
355
+ cmds:
356
+ - echo "All checks passed"
357
+
358
+ check:consumer:
359
+ desc: "Run the consumer-safe Deft quality gate for vendored installs (#1519)."
360
+ deps:
361
+ - doctor
362
+ - toolchain:check
363
+ - verify:branch
364
+ - verify:cache-fresh
365
+ - verify:wip-cap
366
+ - vbrief:validate
367
+ - verify-strategy-output
368
+ cmds:
369
+ - echo "Consumer checks passed"
370
+
371
+ # D4 (#1124): framework self-check wrapper that passes
372
+ # --allow-over-cap so deft's own landing-day overage (pending/+active/
373
+ # currently >> 10, resolved via D1 scope:demote --batch per umbrella
374
+ # v3) does not break framework `task check`. Consumer projects depend
375
+ # on `verify:wip-cap` directly (without --allow-over-cap) so a
376
+ # stale-branch / --force-merge over-cap state fails their `task check`
377
+ # loudly. Mirrors the verify:cache-fresh / verify:branch
378
+ # --allow-missing-* tolerance pattern.
379
+ verify-wip-cap-framework-self-check:
380
+ internal: true
381
+ desc: "Framework self-check shim for verify:wip-cap (#1124)."
382
+ dir: '{{.USER_WORKING_DIR}}'
383
+ env:
384
+ PYTHONUTF8: "1"
385
+ cmds:
386
+ - task: verify:wip-cap
387
+ vars:
388
+ CLI_ARGS: "--allow-over-cap"
389
+
390
+ # s2-deterministic-gate (#1166): deterministic validation gate for strategy
391
+ # output shape. Runs on every `task check` (including CI). Implemented in
392
+ # scripts/validate_strategy_output.py. Respects Grok Build Windows rules
393
+ # (plain uv python invocation, no pipes in this Taskfile context).
394
+ verify-strategy-output:
395
+ desc: "Deterministic v0.20 strategy output shape gate (#1166 s2). Fails on non-date-prefixed vBRIEFs in lifecycle dirs, missing PROJECT-DEFINITION.vbrief.json, or legacy specification.vbrief.json in user projects."
396
+ dir: '{{.USER_WORKING_DIR}}'
397
+ deps:
398
+ - task: verify:_ts-build
399
+ vars:
400
+ DEFT_ROOT: "{{.TASKFILE_DIR}}"
401
+ cmds:
402
+ # Oracle/fallback (parity): scripts/validate_strategy_output.py (#1854 s3).
403
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" validate-strategy-output --project-root "{{.USER_WORKING_DIR}}"
404
+
405
+ # Pack-projection drift gate (#1294 / #1283, ADR-001). User-facing alias for
406
+ # `packs:verify-drift`, defined at the root Taskfile so it carries the
407
+ # documented `verify:*` prefix that the gate stack + `task check` reference
408
+ # while the implementation lives in the `packs:` include namespace (mirrors
409
+ # the established triage:* / scope:* alias precedent above). Wired into
410
+ # `check:framework-source` deps. Forwards {{.CLI_ARGS}} so --source / --output
411
+ # overrides reach the script.
412
+ verify:pack-drift:
413
+ desc: "Fail when meta/lessons.md drifts from the canonical lessons-pack source (#1294 / ADR-001). Alias for packs:verify-drift; wired into `task check`."
414
+ cmds:
415
+ - task: packs:verify-drift
416
+ vars:
417
+ CLI_ARGS: "{{.CLI_ARGS}}"
418
+
419
+ verify:no-task-runtime:
420
+ desc: "Fail when runtime Python code hard-depends on go-task (#1659)."
421
+ deps:
422
+ - task: verify:_ts-build
423
+ vars:
424
+ DEFT_ROOT: "{{.TASKFILE_DIR}}"
425
+ cmds:
426
+ # Oracle/fallback (parity): scripts/verify_no_task_runtime.py (#1854 s3).
427
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" verify-no-task-runtime
428
+
429
+ # `task check:slow` runs the @pytest.mark.slow lane that the default
430
+ # `task check` skips (#975). The slow lane is dominated by the
431
+ # triage_bootstrap watchdog regression suite (5 of the 6 marked tests),
432
+ # which burns ~5.85s on real time.sleep / thread joins -- the proper
433
+ # monkeypatch refactor is tracked as a follow-up to #975. The `-o
434
+ # addopts=` reset overrides the pyproject default of `-m 'not slow'`
435
+ # so the `-m slow` selector here actually picks up the marked tests.
436
+ check:slow:
437
+ desc: "Run the @pytest.mark.slow test lane (watchdog regression suite excluded from `task check` by default, #975)"
438
+ cmds:
439
+ # `--project` pins uv to the framework root so ancestor pyproject.toml
440
+ # files cannot hijack the resolver via uv's upward walk (#1011).
441
+ - uv --project "{{.TASKFILE_DIR}}" run pytest tests/ -o addopts= -m slow
442
+
443
+ test:
444
+ desc: Run test suite (alias for core:test)
445
+ cmds:
446
+ - task: core:test
447
+ test:coverage:
448
+ desc: Run tests with coverage (alias for core:test:coverage)
449
+ cmds:
450
+ - task: core:test:coverage
451
+ lint:
452
+ desc: Lint and type-check Python code (alias for core:lint)
453
+ cmds:
454
+ - task: core:lint
455
+ fmt:
456
+ desc: Format Python code (alias for core:fmt)
457
+ cmds:
458
+ - task: core:fmt
459
+ build:
460
+ desc: Package framework for distribution (alias for core:build)
461
+ cmds:
462
+ - task: core:build
463
+ clean:
464
+ desc: Clean generated artifacts (alias for core:clean)
465
+ cmds:
466
+ - task: core:clean
467
+ validate:
468
+ desc: Validate all markdown files (alias for core:validate)
469
+ cmds:
470
+ - task: core:validate
471
+ install:
472
+ desc: Install deft (alias for install:install)
473
+ cmds:
474
+ - task: install:install
475
+ uninstall:
476
+ desc: Remove deft entry from AGENTS.md (alias for install:uninstall)
477
+ cmds:
478
+ - task: install:uninstall
479
+ # User-facing upgrade entrypoint (#1061). Aliases the install:upgrade
480
+ # wrapper that delegates to `run upgrade`. Cited by the doctor's
481
+ # failure prose and docs/install-manifest.md as the canonical
482
+ # post-drift repair entrypoint for the AGENTS.md / manifest /
483
+ # .deft-version triple.
484
+ upgrade:
485
+ desc: "Upgrade deft framework -- refresh AGENTS.md + write install manifest + regenerate .deft-version (alias for install:upgrade, #1061)"
486
+ cmds:
487
+ - task: install:upgrade
488
+ stats:
489
+ desc: Show framework statistics (alias for core:stats)
490
+ cmds:
491
+ - task: core:stats
492
+
493
+ # #1272: canonical doctor surface -- thin shim that forwards to
494
+ # ``.deft/core/run doctor``. The ``run`` CLI owns the diagnostic
495
+ # logic (system deps, framework layout, root Taskfile.yml include
496
+ # health) and the optional interactive repair path. The task
497
+ # accepts user-facing flags (``--session`` / ``--fix`` / ``--json``
498
+ # / ``--quiet``) via ``{{.CLI_ARGS}}`` so per
499
+ # ``conventions/task-caching.md`` (#574) MUST NOT declare
500
+ # ``sources:`` / ``generates:`` -- a cached cmds skip would silently
501
+ # swallow the flags. The deprecated ``task framework:doctor`` task
502
+ # in ``tasks/framework.yml`` now prints a redaction notice pointing
503
+ # the operator at this surface.
504
+ doctor:
505
+ desc: "Canonical doctor surface (#1272) -- task doctor [-- --session | --fix | --json | --quiet]. Shim for `.deft/core/run doctor`."
506
+ dir: '{{.USER_WORKING_DIR}}'
507
+ env:
508
+ PYTHONUTF8: "1"
509
+ cmds:
510
+ - uv --project "{{.TASKFILE_DIR}}" run --frozen python "{{.TASKFILE_DIR}}/run" doctor {{.CLI_ARGS}}
511
+
512
+ setup:
513
+ desc: "Idempotent local-dev setup: configure git hooks (#747); detect-and-prompt ghx (#884). Sets core.hooksPath=.githooks so .githooks/pre-commit + .githooks/pre-push run."
514
+ dir: '{{.USER_WORKING_DIR}}'
515
+ env:
516
+ PYTHONUTF8: "1"
517
+ cmds:
518
+ # Inline POSIX-sh under go-task's mvdan/sh interpreter -- cross-platform.
519
+ # `git config core.hooksPath .githooks` is itself idempotent, but we
520
+ # detect the no-op so the task prints a friendly message rather than
521
+ # silently re-asserting on every invocation.
522
+ - |
523
+ configured=$(git config --get core.hooksPath || true)
524
+ if [ "$configured" = ".githooks" ]; then
525
+ echo "✓ core.hooksPath already set to .githooks (no change)."
526
+ else
527
+ git config core.hooksPath .githooks
528
+ echo "✓ core.hooksPath set to .githooks (#747 branch gate active)."
529
+ fi
530
+ # #814: Detect a Python interpreter whose stdout defaults to a
531
+ # non-UTF-8 Windows code page (cp1252 / cp437). Informational only --
532
+ # the deft hook scripts themselves self-reconfigure to UTF-8 at
533
+ # main() entry, so this warning surfaces a fact about the user's
534
+ # environment, not a defect that blocks setup. We do NOT auto-set
535
+ # PYTHONIOENCODING because mutating the user's environment would
536
+ # surprise other tooling (out-of-scope per the issue body).
537
+ - |
538
+ python_bin="${DEFT_PYTHON:-}"
539
+ if [ -z "$python_bin" ]; then
540
+ if command -v python3 >/dev/null 2>&1; then
541
+ python_bin=python3
542
+ elif command -v python >/dev/null 2>&1; then
543
+ python_bin=python
544
+ fi
545
+ fi
546
+ if [ -n "$python_bin" ]; then
547
+ # NOTE: we explicitly unset PYTHONUTF8 / PYTHONIOENCODING in the
548
+ # subshell so the probe measures what Python would do under git's
549
+ # hook environment (which inherits the user's shell, NOT the
550
+ # Taskfile root env: block). Without the unset, the root-level
551
+ # `env: PYTHONUTF8: "1"` (#540) masks cp1252 here and the warning
552
+ # would never surface even when the user actually has the bug.
553
+ enc=$(unset PYTHONUTF8 PYTHONIOENCODING; "$python_bin" -c "import sys; print((sys.stdout.encoding or '').lower())" 2>/dev/null || true)
554
+ case "$enc" in
555
+ cp1252|cp437|charmap)
556
+ echo ""
557
+ echo "WARN: Detected Python stdout encoding '$enc' (Windows default). Deft hooks"
558
+ echo "print non-ASCII glyphs and may crash without UTF-8 stdout. Either:"
559
+ echo " (a) set the user-environment variable PYTHONIOENCODING=utf-8 (one-time,"
560
+ echo " via System Properties > Environment Variables), OR"
561
+ echo " (b) add \$env:PYTHONIOENCODING='utf-8' to your PowerShell profile."
562
+ echo "The deft hook scripts also self-reconfigure as of #814, so this"
563
+ echo "warning is informational on current versions."
564
+ ;;
565
+ esac
566
+ fi
567
+ # #884: ghx adoption -- consent-gated install of the brunoborges/ghx
568
+ # GitHub CLI cache proxy. Default invocation here passes --check so
569
+ # `task setup` never prompts on a clean re-run; operators wanting to
570
+ # opt in run `task setup:ghx` (defined below) which is the
571
+ # interactive entry point. The script is pure-stdlib so it works
572
+ # before `uv sync` has run on a fresh worktree; `uv run` is still
573
+ # the canonical dispatcher to keep the python interpreter consistent
574
+ # with every other Taskfile-dispatched script. `--project` pins uv
575
+ # to the framework root so ancestor pyproject.toml files cannot
576
+ # hijack the resolver via uv's upward walk (#1011).
577
+ - uv --project "{{.TASKFILE_DIR}}" run python "{{.TASKFILE_DIR}}/scripts/setup_ghx.py" --check
578
+
579
+ setup:ghx:
580
+ desc: "Consent-gated ghx (brunoborges/ghx) installer (#884) -- task setup:ghx [-- --yes]"
581
+ dir: '{{.USER_WORKING_DIR}}'
582
+ env:
583
+ PYTHONUTF8: "1"
584
+ # Per `conventions/task-caching.md` (#574): no `sources:` / `generates:`
585
+ # because the script forwards user-facing flags via {{.CLI_ARGS}}
586
+ # (notably --yes for non-interactive CI / scripted approval).
587
+ cmds:
588
+ - uv --project "{{.TASKFILE_DIR}}" run python "{{.TASKFILE_DIR}}/scripts/setup_ghx.py" {{.CLI_ARGS}}
589
+
590
+ # Release pipeline tasks (#74 + #716 safety hardening, namespace flatten #718).
591
+ #
592
+ # Defined inline at the root Taskfile rather than via `includes: release: ./tasks/release.yml`
593
+ # because go-task concatenates the namespace key with each inner task name -- so an inner
594
+ # task named `release:` under namespace `release:` would install as `task release:release`,
595
+ # not `task release` (the documented invocation in skills/deft-directive-release/SKILL.md
596
+ # and CHANGELOG entries from #74/#716). See #718 for the full root-cause analysis.
597
+ #
598
+ # Sibling pattern: tasks/pr.yml uses inner task name `check-protected-issues` (no `pr:`
599
+ # repeat) so the include-namespace mechanism produces `pr:check-protected-issues`. The
600
+ # release pipeline cannot use that pattern because it needs BOTH a top-level `release`
601
+ # name AND `release:e2e` / `release:publish` / `release:rollback` sub-names.
602
+ #
603
+ # Per `conventions/task-caching.md` (#574): tasks that accept user-facing recovery flags
604
+ # via {{.CLI_ARGS}} (here: --dry-run / --skip-tag / --skip-release / --allow-dirty /
605
+ # --repo / --no-draft / --allow-low-downloads / --allow-data-loss / --force-strict-0 /
606
+ # --owner / --keep-repo) MUST NOT declare `sources:` / `generates:` -- the cached `cmds:`
607
+ # skip would silently discard the recovery flag.
608
+ #
609
+ # Path resolution uses `{{.TASKFILE_DIR}}/scripts/<script>.py` directly because these
610
+ # tasks live in the root Taskfile.yml where `{{.TASKFILE_DIR}}` already resolves to the
611
+ # deft/ root (no per-subfile DEFT_ROOT joinPath dance is needed -- see Taskfile.yml
612
+ # header comment for why `DEFT_ROOT` is intentionally absent at the root level).
613
+ #
614
+ # Companion scripts: scripts/release.py, scripts/release_publish.py,
615
+ # scripts/release_rollback.py, scripts/release_e2e.py
616
+ # Companion tests: tests/cli/test_release.py,
617
+ # tests/cli/test_release_publish.py,
618
+ # tests/cli/test_release_rollback.py,
619
+ # tests/cli/test_release_e2e.py
620
+ # Refs #74, #233, #642, #635, #709, #710, #716, #718.
621
+ release:
622
+ desc: "Automate the v0.X.Y release flow (#74) -- task release -- <version> [--dry-run] [--skip-tag] [--skip-release] [--no-draft]"
623
+ deps: [ts:build]
624
+ dir: '{{.USER_WORKING_DIR}}'
625
+ cmds:
626
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" release {{.CLI_ARGS}}
627
+
628
+ release:publish:
629
+ desc: "Flip a draft GitHub release to public (#716) -- task release:publish -- <version> [--dry-run] [--repo OWNER/REPO]"
630
+ deps: [ts:build]
631
+ dir: '{{.USER_WORKING_DIR}}'
632
+ cmds:
633
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" release-publish {{.CLI_ARGS}}
634
+
635
+ release:rollback:
636
+ desc: "State-aware release unwind (#716) -- task release:rollback -- <version> [--dry-run] [--allow-low-downloads N] [--allow-data-loss] [--force-strict-0]"
637
+ deps: [ts:build]
638
+ dir: '{{.USER_WORKING_DIR}}'
639
+ cmds:
640
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" release-rollback {{.CLI_ARGS}}
641
+
642
+ release:e2e:
643
+ desc: "End-to-end release rehearsal against an auto-created+destroyed temp repo (#716) -- task release:e2e [-- --dry-run] [--owner OWNER] [--keep-repo]"
644
+ deps: [ts:build]
645
+ dir: '{{.USER_WORKING_DIR}}'
646
+ cmds:
647
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" release-e2e {{.CLI_ARGS}}
648
+
649
+ # ------------------------------------------------------------------
650
+ # Triage v1 user-facing alias tasks (#845, #913).
651
+ #
652
+ # The four triage fragments are namespaced under their unique include
653
+ # keys (`triage-cache`, `triage-actions`, `triage-bulk`,
654
+ # `triage-bootstrap`) -- a single shared `triage:` include namespace
655
+ # is not supported by go-task v3 (two includes cannot share a key).
656
+ # The aliases below provide the documented `task triage:<verb>`
657
+ # user-facing surface that vBRIEFs / UPGRADING.md / scripts/triage_*.py
658
+ # describe. Each alias delegates to the underlying namespaced task
659
+ # and forwards `{{.CLI_ARGS}}` so flags (`--repo`, `--reason`, etc.)
660
+ # reach the script. The inner tasks in each fragment are
661
+ # `internal: true` so the fragment-namespace forms
662
+ # (`triage-cache:cache`, `triage-actions:accept`, `triage-bulk:bulk-defer`,
663
+ # `triage-bootstrap:bootstrap`) drop out of `task -l`; only the
664
+ # documented `triage:*` aliases below appear in the listing. The
665
+ # internal tasks remain CALLABLE for legacy invocations (e.g. recap
666
+ # text in `scripts/triage_bootstrap.py` still prints the namespaced
667
+ # forms, which continue to dispatch correctly via the fragment
668
+ # include).
669
+ #
670
+ # Aliases are inline at the root Taskfile rather than in a separate
671
+ # fragment because they cross include namespaces and must exist
672
+ # regardless of which fragments are present.
673
+ #
674
+ # Mirrors the established #718 release-pipeline flatten precedent
675
+ # (release: tasks defined inline at the root Taskfile so go-task
676
+ # does not double-prefix them).
677
+ # ------------------------------------------------------------------
678
+ # task triage:cache and task triage:show were removed in #883 Story 3.
679
+ # The unified cache:* surface (cache:fetch-all, cache:get) is the
680
+ # canonical replacement; see UPGRADING.md for migration text.
681
+
682
+ # ------------------------------------------------------------------
683
+ # N10 (#1150): bare-invocation `task triage` / `task scope` print a
684
+ # categorized verb list grouped by role (Session-start, State verbs,
685
+ # Read verbs, Lifecycle, Subscription mutation, Archive-rotation /
686
+ # Promote-demote, Activate-complete, Reversibility, Decomposition).
687
+ # The registry + renderer live in scripts/triage_help.py so every
688
+ # verb is documented in one place. Each existing `triage:X` /
689
+ # `scope:X` alias forwards `--help` to the same registry via the
690
+ # `intercept_help` shim called from each verb script's `main()`.
691
+ #
692
+ # Defined at the root Taskfile (not in a fragment) because the bare
693
+ # target shares the `triage:` / `scope:` prefix with the documented
694
+ # alias surface and must coexist with `triage:accept`,
695
+ # `scope:promote`, etc. go-task v3 treats `triage` and `triage:accept`
696
+ # as distinct task names; the same precedent established by `release`
697
+ # + `release:publish` in this file (see #718 root-cause rationale).
698
+ # ------------------------------------------------------------------
699
+ triage:
700
+ desc: "Print the categorized triage verb list (#1150 / N10). Run `task triage:<verb> --help` for usage examples."
701
+ dir: '{{.USER_WORKING_DIR}}'
702
+ env:
703
+ PYTHONUTF8: "1"
704
+ cmds:
705
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" triage-help triage
706
+
707
+ scope:
708
+ desc: "Print the categorized scope verb list (#1150 / N10). Run `task scope:<verb> --help` for usage examples."
709
+ dir: '{{.USER_WORKING_DIR}}'
710
+ env:
711
+ PYTHONUTF8: "1"
712
+ cmds:
713
+ - node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" triage-help scope
714
+
715
+ triage:accept:
716
+ desc: "Accept an issue for triage. Records an audit entry. (#845 Story 3)"
717
+ cmds:
718
+ - task: triage-actions:accept
719
+ vars:
720
+ CLI_ARGS: "{{.CLI_ARGS}}"
721
+
722
+ triage:reject:
723
+ desc: "Reject an issue. Closes upstream via gh + applies triage-rejected label; rolls audit back on gh failure. (#845 Story 3)"
724
+ cmds:
725
+ - task: triage-actions:reject
726
+ vars:
727
+ CLI_ARGS: "{{.CLI_ARGS}}"
728
+
729
+ triage:defer:
730
+ desc: "Defer an issue. Records an audit entry. (#845 Story 3)"
731
+ cmds:
732
+ - task: triage-actions:defer
733
+ vars:
734
+ CLI_ARGS: "{{.CLI_ARGS}}"
735
+
736
+ triage:needs-ac:
737
+ desc: "Mark an issue as needing acceptance criteria + post AC-request comment upstream. (#845 Story 3)"
738
+ cmds:
739
+ - task: triage-actions:needs-ac
740
+ vars:
741
+ CLI_ARGS: "{{.CLI_ARGS}}"
742
+
743
+ triage:mark-duplicate:
744
+ desc: "Link an issue as a duplicate of another (validated against Story 1 cache). (#845 Story 3)"
745
+ cmds:
746
+ - task: triage-actions:mark-duplicate
747
+ vars:
748
+ CLI_ARGS: "{{.CLI_ARGS}}"
749
+
750
+ triage:status:
751
+ desc: "Print the latest triage decision for an issue. Read-only. (#845 Story 3)"
752
+ cmds:
753
+ - task: triage-actions:status
754
+ vars:
755
+ CLI_ARGS: "{{.CLI_ARGS}}"
756
+
757
+ triage:reset:
758
+ desc: "Reset an issue's triage state. Appends a reset audit entry referencing prior; does NOT delete history. (#845 Story 3)"
759
+ cmds:
760
+ - task: triage-actions:reset
761
+ vars:
762
+ CLI_ARGS: "{{.CLI_ARGS}}"
763
+
764
+ triage:history:
765
+ desc: "Print the full triage timeline for an issue, ordered by timestamp. Read-only. (#845 Story 3)"
766
+ cmds:
767
+ - task: triage-actions:history
768
+ vars:
769
+ CLI_ARGS: "{{.CLI_ARGS}}"
770
+
771
+ triage:bulk-accept:
772
+ desc: "Bulk accept cached candidates -- task triage:bulk-accept -- --repo OWNER/NAME [--label L] [--author A] [--age-days N] [--cluster C] [--re-action] (#845 Story 4 / #915)"
773
+ cmds:
774
+ - task: triage-bulk:bulk-accept
775
+ vars:
776
+ CLI_ARGS: "{{.CLI_ARGS}}"
777
+
778
+ triage:bulk-reject:
779
+ desc: "Bulk reject cached candidates -- task triage:bulk-reject -- --repo OWNER/NAME --reason 'why' [--label L] [--author A] [--age-days N] [--cluster C] [--re-action] (#845 Story 4 / #915)"
780
+ cmds:
781
+ - task: triage-bulk:bulk-reject
782
+ vars:
783
+ CLI_ARGS: "{{.CLI_ARGS}}"
784
+
785
+ triage:bulk-defer:
786
+ desc: "Bulk defer cached candidates -- task triage:bulk-defer -- --repo OWNER/NAME [--label L] [--author A] [--age-days N] [--cluster C] [--re-action] (#845 Story 4 / #915)"
787
+ cmds:
788
+ - task: triage-bulk:bulk-defer
789
+ vars:
790
+ CLI_ARGS: "{{.CLI_ARGS}}"
791
+
792
+ triage:bulk-needs-ac:
793
+ desc: "Bulk needs-ac cached candidates -- task triage:bulk-needs-ac -- --repo OWNER/NAME [--label L] [--author A] [--age-days N] [--cluster C] [--re-action] (#845 Story 4 / #915)"
794
+ cmds:
795
+ - task: triage-bulk:bulk-needs-ac
796
+ vars:
797
+ CLI_ARGS: "{{.CLI_ARGS}}"
798
+
799
+ triage:refresh-active:
800
+ desc: "Pre-swarm freshness gate (#845 Story 4) -- detects drift between cached and live `gh issue view` for every issue referenced in vbrief/active/*.vbrief.json"
801
+ cmds:
802
+ - task: triage-bulk:refresh-active
803
+ vars:
804
+ CLI_ARGS: "{{.CLI_ARGS}}"
805
+
806
+ triage:bootstrap:
807
+ desc: "Run the triage v1 idempotent installer (#845 Story 6)."
808
+ cmds:
809
+ - task: triage-bootstrap:bootstrap
810
+ vars:
811
+ CLI_ARGS: "{{.CLI_ARGS}}"
812
+
813
+ triage:reconcile:
814
+ desc: "Self-heal the triage audit log (#1468): backfill missing `accept` decisions for proposed/pending/active vBRIEFs carrying an x-vbrief/github-issue reference, without a cache re-fetch. Idempotent. -- task triage:reconcile [-- --repo OWNER/NAME] [--dry-run] [--json]"
815
+ cmds:
816
+ - task: triage-reconcile:reconcile
817
+ vars:
818
+ CLI_ARGS: "{{.CLI_ARGS}}"
819
+
820
+ triage:scope:
821
+ desc: "Inspect / mutate / diff the typed plan.policy.triageScope[] subscription + triageScopeIgnores[] (#1131 / D12, #1133 / D14, #1182 / D14c). -- task triage:scope -- [--list] [--add-label=L | --add-milestone=M | --ignore-label=L] [--diff-from-upstream --repo OWNER/NAME] [--refresh-denominator --repo OWNER/NAME --count N]"
822
+ cmds:
823
+ - task: triage-scope:scope
824
+ vars:
825
+ CLI_ARGS: "{{.CLI_ARGS}}"
826
+
827
+ triage:scope-drift:
828
+ desc: "Detect subscription drift (#1133 / D14): unsubscribed labels/milestones on cached open issues. -- task triage:scope-drift [-- --ignore-label=L | --ignore-milestone=M]"
829
+ cmds:
830
+ - task: triage-scope-drift:scope-drift
831
+ vars:
832
+ CLI_ARGS: "{{.CLI_ARGS}}"
833
+
834
+ triage:subscribe:
835
+ desc: "Subscribe to a label / milestone / issue (#1133 / D14). -- task triage:subscribe -- (--label=L | --milestone=M | --issue=N)"
836
+ cmds:
837
+ - task: triage-subscribe:subscribe
838
+ vars:
839
+ CLI_ARGS: "{{.CLI_ARGS}}"
840
+
841
+ triage:unsubscribe:
842
+ desc: "Unsubscribe a label / milestone / issue (#1133 / D14). -- task triage:unsubscribe -- (--label=L | --milestone=M | --issue=N)"
843
+ cmds:
844
+ - task: triage-subscribe:unsubscribe
845
+ vars:
846
+ CLI_ARGS: "{{.CLI_ARGS}}"
847
+
848
+ triage:classify:
849
+ desc: "Inspect / validate the auto-classification surface (#1129 / D10). -- task triage:classify -- [--list | --validate]"
850
+ cmds:
851
+ - task: triage-classify:classify
852
+ vars:
853
+ CLI_ARGS: "{{.CLI_ARGS}}"
854
+
855
+ triage:summary:
856
+ desc: "Emit the one-line triage state for the session-start ritual (D2 / #1122). Always exits 0; appends a JSONL record to vbrief/.eval/summary-history.jsonl. -- task triage:summary -- [--json] [--no-history]"
857
+ cmds:
858
+ - task: triage-summary:summary
859
+ vars:
860
+ CLI_ARGS: "{{.CLI_ARGS}}"
861
+
862
+ triage:queue:
863
+ desc: "Print the ranked triage queue (#1128 / D11). -- task triage:queue [-- --repo OWNER/NAME] [--limit N]"
864
+ cmds:
865
+ - task: triage-queue:queue
866
+ vars:
867
+ CLI_ARGS: "{{.CLI_ARGS}}"
868
+
869
+ triage:show:
870
+ desc: "Per-issue triage detail (#1128 / D11). -- task triage:show -- <N> [--repo OWNER/NAME]"
871
+ cmds:
872
+ - task: triage-queue:show
873
+ vars:
874
+ CLI_ARGS: "{{.CLI_ARGS}}"
875
+
876
+ triage:audit:
877
+ desc: "Audit-log surface (#1128 / D11, #1180). -- task triage:audit [-- --format=text|json] [--vbrief-staleness] [--since=<window>] [--action=<verb>] [--repo OWNER/NAME]"
878
+ cmds:
879
+ - task: triage-queue:audit
880
+ vars:
881
+ CLI_ARGS: "{{.CLI_ARGS}}"
882
+
883
+ triage:welcome:
884
+ desc: "Run the 6-phase onboarding ritual (N3 / #1143): detect prior state, prompt subscription scope, run triage:bootstrap, prompt wipCap, offer WIP relief, print triage:summary. Idempotent. -- task triage:welcome [-- --no-subprocess]"
885
+ cmds:
886
+ - task: triage-welcome:welcome
887
+ vars:
888
+ CLI_ARGS: "{{.CLI_ARGS}}"
889
+ DEFT_TASK_PREFIX:
890
+ sh: |
891
+ task_name='{{.TASK}}'
892
+ suffix='triage:welcome'
893
+ prefix="${task_name%$suffix}"
894
+ if [ "$prefix" = "$task_name" ]; then
895
+ prefix=''
896
+ fi
897
+ printf '%s' "$prefix"
898
+
899
+ triage:smoketest:
900
+ desc: "Run the N6 (#1146) end-to-end smoketest against the hermetic 20-issue fixture; exits 0 on PASS / 1 on first failure. -- task triage:smoketest [-- --verbose] [--keep-tempdir] [--cache-only]"
901
+ cmds:
902
+ - task: triage-smoketest:smoketest
903
+ vars:
904
+ CLI_ARGS: "{{.CLI_ARGS}}"
905
+
906
+ # D15 (#1134): scope:undo audit-log reversibility verb. Delegates to
907
+ # the standalone fragment include `scope-undo`. Reverses a single
908
+ # audit entry by decision_id or every entry tagged with batch_id;
909
+ # terminal actions (`complete` / `fail`) are REFUSED.
910
+ scope:undo:
911
+ desc: "Reverse a scope-lifecycle audit entry (#1134 / D15). -- task scope:undo -- <decision_id> | --decision-id=<uuid> | --batch-id=<uuid> [--dry-run]"
912
+ cmds:
913
+ - task: scope-undo:undo
914
+ vars:
915
+ CLI_ARGS: "{{.CLI_ARGS}}"
916
+
917
+ # N7 (#1147): slice:record-existing backfill verb. Retrofits a
918
+ # vbrief/.eval/slices.jsonl entry for hand-filed umbrella cohorts that
919
+ # D13's writer (#1132) never saw because they were filed via
920
+ # `gh issue create` / `issue_write` MCP rather than via a slicing
921
+ # skill. Companion `slice:list` exposes the read surface.
922
+ slice:record-existing:
923
+ desc: "Retrofit a slices.jsonl entry for a hand-filed cohort (#1147 / N7). -- task slice:record-existing -- --umbrella=N --children=A,B,C [--wave-1=A,B] [--wave-2=C] [--actor=manual:operator] [--expected-close-signal=all-children-merged] [--sliced-at=ISO] [--notes=TEXT] [--dry-run] [--force] [--skip-validation] [--repo OWNER/NAME]"
924
+ cmds:
925
+ - task: slice-record:record-existing
926
+ vars:
927
+ CLI_ARGS: "{{.CLI_ARGS}}"
928
+
929
+ slice:list:
930
+ desc: "List recorded slices in vbrief/.eval/slices.jsonl (#1147 / N7). -- task slice:list [-- --json]"
931
+ cmds:
932
+ - task: slice-record:list
933
+ vars:
934
+ CLI_ARGS: "{{.CLI_ARGS}}"