@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.
- package/.githooks/pre-commit +10 -128
- package/.githooks/pre-push +8 -108
- package/Taskfile.yml +48 -58
- package/UPGRADING.md +19 -3
- package/docs/assets/directive-lifecycle-diagram.png +0 -0
- package/docs/directive-lifecycle.md +73 -0
- package/docs/getting-started.md +5 -1
- package/package.json +3 -3
- package/packs/skills/skills-pack-0.1.json +1 -1
- package/packs/strategies/strategies-pack-0.1.json +19 -19
- package/scm/github.md +37 -6
- package/skills/deft-directive-setup/SKILL.md +24 -15
- package/strategies/speckit.md +14 -14
- package/strategies/v0-20-contract.md +12 -1
- package/tasks/change.yml +16 -31
- package/tasks/ci.yml +8 -0
- package/tasks/commit.yml +12 -19
- package/tasks/core.yml +10 -0
- package/tasks/engine.yml +42 -0
- package/tasks/framework.yml +3 -0
- package/tasks/install.yml +20 -19
- package/tasks/migrate.yml +26 -15
- package/tasks/project.yml +26 -0
- package/tasks/toolchain.yml +15 -5
- package/tasks/vbrief.yml +4 -3
- package/tasks/verify.yml +12 -14
- package/templates/agents-entry.md +1 -1
- package/scripts/_agents_md.py +0 -494
- package/scripts/_cache_fetch.py +0 -635
- package/scripts/_cache_quota.py +0 -529
- package/scripts/_cache_refresh.py +0 -163
- package/scripts/_cache_validate.py +0 -209
- package/scripts/_content_root.py +0 -42
- package/scripts/_doctor_state.py +0 -277
- package/scripts/_event_detect.py +0 -305
- package/scripts/_events.py +0 -514
- package/scripts/_lifecycle_hygiene.py +0 -568
- package/scripts/_pathspec.py +0 -91
- package/scripts/_policy_show_cli.py +0 -266
- package/scripts/_precutover.py +0 -92
- package/scripts/_project_context.py +0 -224
- package/scripts/_project_definition_io.py +0 -164
- package/scripts/_relocate_snapshot.py +0 -209
- package/scripts/_relocate_states.py +0 -343
- package/scripts/_resolve_preflight_path.py +0 -152
- package/scripts/_safe_subprocess.py +0 -167
- package/scripts/_session_start_hook.py +0 -205
- package/scripts/_sor_gate_diff.py +0 -365
- package/scripts/_stdio_utf8.py +0 -59
- package/scripts/_triage_bootstrap_gitignore.py +0 -904
- package/scripts/_triage_classify_cli.py +0 -122
- package/scripts/_triage_queue_cli.py +0 -625
- package/scripts/_triage_scope_cli.py +0 -343
- package/scripts/_triage_scope_drift_cli.py +0 -121
- package/scripts/_triage_scope_ignores.py +0 -286
- package/scripts/_triage_scope_milestone.py +0 -432
- package/scripts/_triage_scope_mutations.py +0 -337
- package/scripts/_triage_scope_renderers.py +0 -207
- package/scripts/_triage_smoketest_stages.py +0 -674
- package/scripts/_triage_subscribe_cli.py +0 -140
- package/scripts/_triage_welcome_cli.py +0 -421
- package/scripts/_vbrief_build.py +0 -239
- package/scripts/_vbrief_fidelity.py +0 -479
- package/scripts/_vbrief_legacy.py +0 -589
- package/scripts/_vbrief_reconciliation.py +0 -883
- package/scripts/_vbrief_routing.py +0 -277
- package/scripts/_vbrief_safety.py +0 -778
- package/scripts/_vbrief_sources.py +0 -312
- package/scripts/_vbrief_speckit.py +0 -262
- package/scripts/_vbrief_story_quality.py +0 -353
- package/scripts/_vbrief_validation.py +0 -299
- package/scripts/build_dist.py +0 -412
- package/scripts/cache.py +0 -1078
- package/scripts/cache_scanner.py +0 -745
- package/scripts/candidates_log.py +0 -432
- package/scripts/capacity_backfill.py +0 -680
- package/scripts/capacity_show.py +0 -653
- package/scripts/ci_local.py +0 -689
- package/scripts/code_structure_validate.py +0 -765
- package/scripts/codebase_default_extractor.py +0 -495
- package/scripts/codebase_map.py +0 -304
- package/scripts/codebase_map_fresh.py +0 -104
- package/scripts/codebase_projection_registry.py +0 -94
- package/scripts/codebase_provider.py +0 -582
- package/scripts/doctor.py +0 -2552
- package/scripts/framework_commands.py +0 -505
- package/scripts/gh_rest.py +0 -882
- package/scripts/github_auth_modes.py +0 -437
- package/scripts/github_body.py +0 -292
- package/scripts/ip_risk.py +0 -531
- package/scripts/issue_emit.py +0 -670
- package/scripts/issue_ingest.py +0 -1064
- package/scripts/migrate_preflight.py +0 -418
- package/scripts/migrate_vbrief.py +0 -2677
- package/scripts/monitor_pr.py +0 -401
- package/scripts/pack_migrate_lessons.py +0 -336
- package/scripts/pack_migrate_patterns.py +0 -254
- package/scripts/pack_migrate_rules.py +0 -350
- package/scripts/pack_migrate_skills.py +0 -423
- package/scripts/pack_migrate_strategies.py +0 -311
- package/scripts/pack_migrate_swarm_spec.py +0 -250
- package/scripts/pack_render.py +0 -434
- package/scripts/packs_slice.py +0 -712
- package/scripts/platform_capabilities.py +0 -336
- package/scripts/policy.py +0 -2826
- package/scripts/policy_set.py +0 -324
- package/scripts/pr_check_closing_keywords.py +0 -524
- package/scripts/pr_check_protected_issues.py +0 -267
- package/scripts/pr_merge_readiness.py +0 -1004
- package/scripts/pr_wait_mergeable.py +0 -669
- package/scripts/prd_render.py +0 -159
- package/scripts/preflight_architecture_sor.py +0 -974
- package/scripts/preflight_branch.py +0 -289
- package/scripts/preflight_cache.py +0 -974
- package/scripts/preflight_gh.py +0 -721
- package/scripts/preflight_implementation.py +0 -272
- package/scripts/preflight_story_start.py +0 -838
- package/scripts/preflight_wip_cap.py +0 -149
- package/scripts/probe_session.py +0 -545
- package/scripts/project_render.py +0 -293
- package/scripts/quarantine_ext.py +0 -237
- package/scripts/reconcile_issues.py +0 -1442
- package/scripts/refresh-path.ps1 +0 -107
- package/scripts/release.py +0 -2030
- package/scripts/release_e2e.py +0 -1011
- package/scripts/release_publish.py +0 -486
- package/scripts/release_rollback.py +0 -980
- package/scripts/relocate.py +0 -1034
- package/scripts/resolve_changelog_unreleased.py +0 -667
- package/scripts/resolve_version.py +0 -490
- package/scripts/resume_conditions.py +0 -706
- package/scripts/ritual_sentinel.py +0 -609
- package/scripts/roadmap_render.py +0 -635
- package/scripts/rule_ownership_lint.py +0 -325
- package/scripts/scm.py +0 -591
- package/scripts/scope_audit_log.py +0 -387
- package/scripts/scope_decompose.py +0 -654
- package/scripts/scope_demote.py +0 -509
- package/scripts/scope_lifecycle.py +0 -1126
- package/scripts/scope_undo.py +0 -772
- package/scripts/session_start.py +0 -406
- package/scripts/setup_ghx.py +0 -339
- package/scripts/setup_windows.ps1 +0 -220
- package/scripts/slice_audit.py +0 -585
- package/scripts/slice_record.py +0 -530
- package/scripts/slice_record_existing.py +0 -692
- package/scripts/slug_normalize.py +0 -178
- package/scripts/spec_render.py +0 -477
- package/scripts/spec_validate.py +0 -238
- package/scripts/subagent_monitor.py +0 -658
- package/scripts/swarm_complete_cohort.py +0 -644
- package/scripts/swarm_launch.py +0 -1206
- package/scripts/swarm_readiness.py +0 -554
- package/scripts/swarm_verify_review_clean.py +0 -438
- package/scripts/swarm_worktrees.py +0 -497
- package/scripts/toolchain-check.py +0 -52
- package/scripts/triage_actions.py +0 -871
- package/scripts/triage_bootstrap.py +0 -1153
- package/scripts/triage_bulk.py +0 -630
- package/scripts/triage_classify.py +0 -932
- package/scripts/triage_help.py +0 -1685
- package/scripts/triage_queue.py +0 -1944
- package/scripts/triage_reconcile.py +0 -581
- package/scripts/triage_refresh.py +0 -643
- package/scripts/triage_scope.py +0 -999
- package/scripts/triage_scope_drift.py +0 -575
- package/scripts/triage_smoketest.py +0 -396
- package/scripts/triage_subscribe.py +0 -399
- package/scripts/triage_summary.py +0 -1011
- package/scripts/triage_welcome.py +0 -1178
- package/scripts/ts_check_lane.py +0 -86
- package/scripts/validate-links.py +0 -64
- package/scripts/validate_strategy_output.py +0 -212
- package/scripts/vbrief_activate.py +0 -228
- package/scripts/vbrief_migrate_conformance.py +0 -368
- package/scripts/vbrief_reconcile_graph.py +0 -306
- package/scripts/vbrief_reconcile_labels.py +0 -460
- package/scripts/vbrief_reconcile_umbrellas.py +0 -741
- package/scripts/vbrief_validate.py +0 -1144
- package/scripts/verify-stubs.py +0 -61
- package/scripts/verify_capacity.py +0 -160
- package/scripts/verify_encoding.py +0 -699
- package/scripts/verify_hooks_installed.py +0 -206
- package/scripts/verify_investigation.py +0 -360
- package/scripts/verify_judgment_gates.py +0 -827
- package/scripts/verify_no_task_runtime.py +0 -171
- package/scripts/verify_scm_boundary.py +0 -509
- package/scripts/verify_session_ritual.py +0 -389
- package/scripts/verify_tools.py +0 -426
- package/scripts/verify_vbrief_conformance.py +0 -478
package/.githooks/pre-commit
CHANGED
|
@@ -1,143 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
# .githooks/pre-commit --
|
|
2
|
+
# .githooks/pre-commit -- deft CLI gates (#2049 / #747 / #798 / #1620).
|
|
3
3
|
#
|
|
4
|
-
# Activated by `git config core.hooksPath .githooks`
|
|
5
|
-
#
|
|
6
|
-
# installer, which copies this hook to the consumer root .githooks/ and sets
|
|
7
|
-
# core.hooksPath for vendored consumer projects (#1463). Verify with:
|
|
8
|
-
#
|
|
9
|
-
# task verify:hooks-installed
|
|
10
|
-
#
|
|
11
|
-
# Pure POSIX-shell so this runs from MSYS / Git for Windows without bash
|
|
12
|
-
# being on PATH. The Python script itself is stdlib-only so it does NOT
|
|
13
|
-
# require `uv` or a virtualenv to be active.
|
|
4
|
+
# Activated by `git config core.hooksPath .githooks` via `task setup` or the
|
|
5
|
+
# deft installer (#1463). Pure POSIX shell; requires `deft` on PATH (no Python).
|
|
14
6
|
|
|
15
|
-
# Resolve repo root (this hook lives at <core.hooksPath>/pre-commit).
|
|
16
7
|
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
|
|
17
8
|
if [ -z "$REPO_ROOT" ]; then
|
|
18
9
|
echo "deft pre-commit: unable to resolve repo root via 'git rev-parse'." >&2
|
|
19
10
|
exit 1
|
|
20
11
|
fi
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# $REPO_ROOT/deft/ (legacy). Because the installer copies this hook to the
|
|
26
|
-
# consumer root .githooks/, it MUST locate the helpers relative to the install
|
|
27
|
-
# root rather than assuming $REPO_ROOT/scripts/. Probe the known layouts and
|
|
28
|
-
# use the first that resolves so the hook works in BOTH layouts.
|
|
29
|
-
SCRIPTS_DIR=""
|
|
30
|
-
for candidate in "$REPO_ROOT/scripts" "$REPO_ROOT/.deft/core/scripts" "$REPO_ROOT/deft/scripts"; do
|
|
31
|
-
if [ -f "$candidate/preflight_branch.py" ]; then
|
|
32
|
-
SCRIPTS_DIR="$candidate"
|
|
33
|
-
break
|
|
34
|
-
fi
|
|
35
|
-
done
|
|
36
|
-
if [ -z "$SCRIPTS_DIR" ]; then
|
|
37
|
-
echo "deft pre-commit: unable to locate the deft scripts directory." >&2
|
|
38
|
-
echo " Looked in scripts/, .deft/core/scripts/, deft/scripts/ under $REPO_ROOT." >&2
|
|
39
|
-
echo " Re-run the deft installer or 'task setup' to wire the hooks correctly." >&2
|
|
40
|
-
exit 1
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# Resolve a usable Python interpreter (#1668). On Windows `python3` is usually
|
|
44
|
-
# absent (only `python.exe` / the `py` launcher exist), and a bare `python3` on
|
|
45
|
-
# PATH is often the Microsoft Store App-Execution-Alias stub that prints
|
|
46
|
-
# "Python was not found" and exits non-zero. Probe DEFT_PYTHON -> python3 ->
|
|
47
|
-
# python -> the `py -3` launcher, validating each candidate by running
|
|
48
|
-
# `--version`, rejecting the alias stub, AND enforcing the framework's Python
|
|
49
|
-
# 3.11+ floor (#1676 -- framework scripts import `from datetime import UTC`,
|
|
50
|
-
# added in 3.11). PY_PREFIX carries the launcher selector (`-3`) when needed.
|
|
51
|
-
PYTHON_BIN=""
|
|
52
|
-
PY_PREFIX=""
|
|
53
|
-
|
|
54
|
-
# _deft_try BIN [PREFIX] -- probe a candidate. Succeeds (and sets PYTHON_BIN /
|
|
55
|
-
# PY_PREFIX) only when the candidate runs, is not the Windows alias stub, and
|
|
56
|
-
# reports a Python version >= 3.11.
|
|
57
|
-
_deft_try() {
|
|
58
|
-
_bin="$1"
|
|
59
|
-
_pre="${2:-}"
|
|
60
|
-
command -v "$_bin" >/dev/null 2>&1 || return 1
|
|
61
|
-
if [ -n "$_pre" ]; then
|
|
62
|
-
_out=$("$_bin" "$_pre" --version 2>&1) || return 1
|
|
63
|
-
else
|
|
64
|
-
_out=$("$_bin" --version 2>&1) || return 1
|
|
65
|
-
fi
|
|
66
|
-
case "$_out" in
|
|
67
|
-
*"Microsoft Store"*|*"was not found"*|*"execution alias"*) return 1 ;;
|
|
68
|
-
esac
|
|
69
|
-
case "$_out" in
|
|
70
|
-
*Python\ [0-9]*) ;;
|
|
71
|
-
*) return 1 ;;
|
|
72
|
-
esac
|
|
73
|
-
# Enforce the 3.11+ floor using POSIX parameter expansion (no sed/awk
|
|
74
|
-
# dependency). Parse major.minor from the "Python X.Y.Z" banner.
|
|
75
|
-
_rest=${_out#*Python }
|
|
76
|
-
_major=${_rest%%.*}
|
|
77
|
-
_rest=${_rest#*.}
|
|
78
|
-
_minor=${_rest%%.*}
|
|
79
|
-
case "$_major" in ''|*[!0-9]*) return 1 ;; esac
|
|
80
|
-
case "$_minor" in ''|*[!0-9]*) return 1 ;; esac
|
|
81
|
-
if [ "$_major" -gt 3 ]; then
|
|
82
|
-
PYTHON_BIN="$_bin"; PY_PREFIX="$_pre"; return 0
|
|
83
|
-
fi
|
|
84
|
-
if [ "$_major" -eq 3 ] && [ "$_minor" -ge 11 ]; then
|
|
85
|
-
PYTHON_BIN="$_bin"; PY_PREFIX="$_pre"; return 0
|
|
86
|
-
fi
|
|
87
|
-
return 1
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if [ -n "${DEFT_PYTHON:-}" ]; then
|
|
91
|
-
# DEFT_PYTHON is the explicit override, but still version-checked so the
|
|
92
|
-
# hooks enforce the same 3.11+ floor as the installer (#1676).
|
|
93
|
-
_deft_try "$DEFT_PYTHON" || true
|
|
94
|
-
if [ -z "$PYTHON_BIN" ]; then
|
|
95
|
-
echo "deft pre-commit: DEFT_PYTHON ($DEFT_PYTHON) is not a usable Python 3.11+ interpreter." >&2
|
|
96
|
-
echo " Point DEFT_PYTHON at a Python 3.11+ executable." >&2
|
|
97
|
-
exit 1
|
|
98
|
-
fi
|
|
99
|
-
else
|
|
100
|
-
_deft_try python3 || _deft_try python || _deft_try py "-3" || true
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
if [ -z "$PYTHON_BIN" ]; then
|
|
104
|
-
echo "deft pre-commit: no usable Python 3.11+ interpreter found." >&2
|
|
105
|
-
echo " Probed python3, python, and the 'py' launcher (rejecting the Windows" >&2
|
|
106
|
-
echo " App-Execution-Alias stub and interpreters older than 3.11)." >&2
|
|
107
|
-
echo " Set DEFT_PYTHON=<absolute python 3.11+ path> or install Python 3.11+." >&2
|
|
13
|
+
if ! command -v deft >/dev/null 2>&1; then
|
|
14
|
+
echo "deft pre-commit: 'deft' not found on PATH." >&2
|
|
15
|
+
echo " Install: npm i -g @deftai/directive" >&2
|
|
108
16
|
exit 1
|
|
109
17
|
fi
|
|
110
18
|
|
|
111
|
-
|
|
112
|
-
# paths that may contain spaces (common on Windows).
|
|
113
|
-
deft_py() {
|
|
114
|
-
if [ -n "$PY_PREFIX" ]; then
|
|
115
|
-
"$PYTHON_BIN" "$PY_PREFIX" "$@"
|
|
116
|
-
else
|
|
117
|
-
"$PYTHON_BIN" "$@"
|
|
118
|
-
fi
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
# Step 1: branch-protection gate (#747).
|
|
122
|
-
deft_py "$SCRIPTS_DIR/preflight_branch.py" --project-root "$REPO_ROOT" || exit $?
|
|
19
|
+
deft verify:branch --project-root "$REPO_ROOT" || exit $?
|
|
123
20
|
|
|
124
|
-
|
|
125
|
-
# files for U+FFFD, CP1252/CP437-as-UTF-8 mojibake, and unexpected BOM.
|
|
126
|
-
# Three-state exit propagates: 0 allowed / 1 corruption blocked with diagnostic
|
|
127
|
-
# / 2 config error. Recurrence chain documented in scripts/verify_encoding.py.
|
|
128
|
-
deft_py "$SCRIPTS_DIR/verify_encoding.py" --project-root "$REPO_ROOT" --staged || exit $?
|
|
21
|
+
deft verify:encoding --staged --project-root "$REPO_ROOT" || exit $?
|
|
129
22
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# namespaced. Three-state exit propagates: 0 clean / 1 bare key blocked with
|
|
133
|
-
# diagnostic / 2 config error. Rule body lives in scripts/verify_vbrief_conformance.py.
|
|
134
|
-
# Guarded on a present vbrief/ corpus so a fresh consumer repo that has not yet
|
|
135
|
-
# created the vBRIEF lifecycle folders is not blocked by the gate's intentional
|
|
136
|
-
# exit-2-on-missing-vbrief/ config-error contract. Also guarded on the gate
|
|
137
|
-
# script being present so a vendored consumer whose .deft/core/scripts/ payload
|
|
138
|
-
# predates this gate (stale-payload upgrade window) is not blocked by a missing
|
|
139
|
-
# script; payload-staleness is surfaced separately by `task doctor`.
|
|
140
|
-
if [ -d "$REPO_ROOT/vbrief" ] && [ -f "$SCRIPTS_DIR/verify_vbrief_conformance.py" ]; then
|
|
141
|
-
deft_py "$SCRIPTS_DIR/verify_vbrief_conformance.py" --project-root "$REPO_ROOT" --staged
|
|
142
|
-
exit $?
|
|
23
|
+
if [ -d "$REPO_ROOT/vbrief" ]; then
|
|
24
|
+
deft verify:vbrief-conformance --staged --project-root "$REPO_ROOT" || exit $?
|
|
143
25
|
fi
|
package/.githooks/pre-push
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
# .githooks/pre-push --
|
|
2
|
+
# .githooks/pre-push -- refspec-aware default-branch push gate (#2049 / #1019 / #1814).
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# core.hooksPath for vendored consumer projects (#1463). Mirrors the
|
|
8
|
-
# pre-commit shape: pre-push defends against the case where a user opted out
|
|
9
|
-
# at commit time (e.g. DEFT_ALLOW_DEFAULT_BRANCH_COMMIT in a single shell)
|
|
10
|
-
# but still tries to push to the default branch in a fresh shell. The same
|
|
11
|
-
# scripts run in both hooks so behavior stays consistent.
|
|
4
|
+
# Pre-push does NOT invoke verify:branch (#747). HEAD-only default-branch
|
|
5
|
+
# protection remains on pre-commit; pre-push relies on preflight-gh for
|
|
6
|
+
# refspec-aware protection (#1814 Option A). Pure POSIX shell; `deft` only.
|
|
12
7
|
|
|
13
8
|
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
|
|
14
9
|
if [ -z "$REPO_ROOT" ]; then
|
|
@@ -16,106 +11,11 @@ if [ -z "$REPO_ROOT" ]; then
|
|
|
16
11
|
exit 1
|
|
17
12
|
fi
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# scripts/, canonical .deft/core/scripts/, or legacy deft/scripts/) rather
|
|
23
|
-
# than assuming $REPO_ROOT/scripts/.
|
|
24
|
-
SCRIPTS_DIR=""
|
|
25
|
-
for candidate in "$REPO_ROOT/scripts" "$REPO_ROOT/.deft/core/scripts" "$REPO_ROOT/deft/scripts"; do
|
|
26
|
-
if [ -f "$candidate/preflight_branch.py" ]; then
|
|
27
|
-
SCRIPTS_DIR="$candidate"
|
|
28
|
-
break
|
|
29
|
-
fi
|
|
30
|
-
done
|
|
31
|
-
if [ -z "$SCRIPTS_DIR" ]; then
|
|
32
|
-
echo "deft pre-push: unable to locate the deft scripts directory." >&2
|
|
33
|
-
echo " Looked in scripts/, .deft/core/scripts/, deft/scripts/ under $REPO_ROOT." >&2
|
|
34
|
-
echo " Re-run the deft installer or 'task setup' to wire the hooks correctly." >&2
|
|
14
|
+
if ! command -v deft >/dev/null 2>&1; then
|
|
15
|
+
echo "deft pre-push: 'deft' not found on PATH." >&2
|
|
16
|
+
echo " Install: npm i -g @deftai/directive" >&2
|
|
35
17
|
exit 1
|
|
36
18
|
fi
|
|
37
19
|
|
|
38
|
-
|
|
39
|
-
# the rationale. On Windows `python3` is usually absent (only `python.exe` /
|
|
40
|
-
# the `py` launcher exist), and a bare `python3` on PATH is often the Microsoft
|
|
41
|
-
# Store App-Execution-Alias stub. Probe DEFT_PYTHON -> python3 -> python -> the
|
|
42
|
-
# `py -3` launcher, validating each candidate by running `--version`, rejecting
|
|
43
|
-
# the alias stub, AND enforcing the framework's Python 3.11+ floor (#1676).
|
|
44
|
-
PYTHON_BIN=""
|
|
45
|
-
PY_PREFIX=""
|
|
46
|
-
|
|
47
|
-
# _deft_try BIN [PREFIX] -- probe a candidate. Succeeds (and sets PYTHON_BIN /
|
|
48
|
-
# PY_PREFIX) only when the candidate runs, is not the Windows alias stub, and
|
|
49
|
-
# reports a Python version >= 3.11.
|
|
50
|
-
_deft_try() {
|
|
51
|
-
_bin="$1"
|
|
52
|
-
_pre="${2:-}"
|
|
53
|
-
command -v "$_bin" >/dev/null 2>&1 || return 1
|
|
54
|
-
if [ -n "$_pre" ]; then
|
|
55
|
-
_out=$("$_bin" "$_pre" --version 2>&1) || return 1
|
|
56
|
-
else
|
|
57
|
-
_out=$("$_bin" --version 2>&1) || return 1
|
|
58
|
-
fi
|
|
59
|
-
case "$_out" in
|
|
60
|
-
*"Microsoft Store"*|*"was not found"*|*"execution alias"*) return 1 ;;
|
|
61
|
-
esac
|
|
62
|
-
case "$_out" in
|
|
63
|
-
*Python\ [0-9]*) ;;
|
|
64
|
-
*) return 1 ;;
|
|
65
|
-
esac
|
|
66
|
-
# Enforce the 3.11+ floor using POSIX parameter expansion (no sed/awk
|
|
67
|
-
# dependency). Parse major.minor from the "Python X.Y.Z" banner.
|
|
68
|
-
_rest=${_out#*Python }
|
|
69
|
-
_major=${_rest%%.*}
|
|
70
|
-
_rest=${_rest#*.}
|
|
71
|
-
_minor=${_rest%%.*}
|
|
72
|
-
case "$_major" in ''|*[!0-9]*) return 1 ;; esac
|
|
73
|
-
case "$_minor" in ''|*[!0-9]*) return 1 ;; esac
|
|
74
|
-
if [ "$_major" -gt 3 ]; then
|
|
75
|
-
PYTHON_BIN="$_bin"; PY_PREFIX="$_pre"; return 0
|
|
76
|
-
fi
|
|
77
|
-
if [ "$_major" -eq 3 ] && [ "$_minor" -ge 11 ]; then
|
|
78
|
-
PYTHON_BIN="$_bin"; PY_PREFIX="$_pre"; return 0
|
|
79
|
-
fi
|
|
80
|
-
return 1
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if [ -n "${DEFT_PYTHON:-}" ]; then
|
|
84
|
-
# DEFT_PYTHON is the explicit override, but still version-checked so the
|
|
85
|
-
# hooks enforce the same 3.11+ floor as the installer (#1676).
|
|
86
|
-
_deft_try "$DEFT_PYTHON" || true
|
|
87
|
-
if [ -z "$PYTHON_BIN" ]; then
|
|
88
|
-
echo "deft pre-push: DEFT_PYTHON ($DEFT_PYTHON) is not a usable Python 3.11+ interpreter." >&2
|
|
89
|
-
echo " Point DEFT_PYTHON at a Python 3.11+ executable." >&2
|
|
90
|
-
exit 1
|
|
91
|
-
fi
|
|
92
|
-
else
|
|
93
|
-
_deft_try python3 || _deft_try python || _deft_try py "-3" || true
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
if [ -z "$PYTHON_BIN" ]; then
|
|
97
|
-
echo "deft pre-push: no usable Python 3.11+ interpreter found." >&2
|
|
98
|
-
echo " Probed python3, python, and the 'py' launcher (rejecting the Windows" >&2
|
|
99
|
-
echo " App-Execution-Alias stub and interpreters older than 3.11)." >&2
|
|
100
|
-
echo " Set DEFT_PYTHON=<absolute python 3.11+ path> or install Python 3.11+." >&2
|
|
101
|
-
exit 1
|
|
102
|
-
fi
|
|
103
|
-
|
|
104
|
-
# deft_py forwards args to the resolved interpreter, preserving quoting for
|
|
105
|
-
# paths that may contain spaces (common on Windows).
|
|
106
|
-
deft_py() {
|
|
107
|
-
if [ -n "$PY_PREFIX" ]; then
|
|
108
|
-
"$PYTHON_BIN" "$PY_PREFIX" "$@"
|
|
109
|
-
else
|
|
110
|
-
"$PYTHON_BIN" "$@"
|
|
111
|
-
fi
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
deft_py "$SCRIPTS_DIR/preflight_branch.py" --project-root "$REPO_ROOT" || exit $?
|
|
115
|
-
|
|
116
|
-
# Step 2: destructive-gh-verb gate (#1019). Reads per-ref stdin lines from
|
|
117
|
-
# git pre-push (one line per ref: <local_ref> <local_oid> <remote_ref> <remote_oid>)
|
|
118
|
-
# and refuses pushes touching the default branch (force-push or otherwise).
|
|
119
|
-
# DEFT_ALLOW_DESTRUCTIVE_GH_VERBS=1 is the per-shell emergency bypass.
|
|
120
|
-
deft_py "$SCRIPTS_DIR/preflight_gh.py" --pre-push-stdin
|
|
20
|
+
deft preflight-gh --pre-push-stdin
|
|
121
21
|
exit $?
|
package/Taskfile.yml
CHANGED
|
@@ -70,9 +70,6 @@ env:
|
|
|
70
70
|
UV_PROJECT: '{{.TASKFILE_DIR}}'
|
|
71
71
|
|
|
72
72
|
includes:
|
|
73
|
-
core:
|
|
74
|
-
taskfile: ./tasks/core.yml
|
|
75
|
-
optional: true
|
|
76
73
|
ts:
|
|
77
74
|
taskfile: ./tasks/ts.yml
|
|
78
75
|
optional: true
|
|
@@ -141,9 +138,6 @@ includes:
|
|
|
141
138
|
pr:
|
|
142
139
|
taskfile: ./tasks/pr.yml
|
|
143
140
|
optional: true
|
|
144
|
-
ci:
|
|
145
|
-
taskfile: ./tasks/ci.yml
|
|
146
|
-
optional: true
|
|
147
141
|
policy:
|
|
148
142
|
taskfile: ./tasks/policy.yml
|
|
149
143
|
optional: true
|
|
@@ -307,6 +301,24 @@ includes:
|
|
|
307
301
|
packs:
|
|
308
302
|
taskfile: ./tasks/packs.yml
|
|
309
303
|
optional: true
|
|
304
|
+
# Maintainer-only Python self-test lanes (#1813 contributor path / #2022
|
|
305
|
+
# Phase 2). `internal: true` hides `core:*` / `ci:*` from `task -l` and
|
|
306
|
+
# blocks direct CLI invocation on consumer installs; only
|
|
307
|
+
# `check:framework-source` below wires them as deps. Consumer `task check`
|
|
308
|
+
# dispatches to `check:consumer` (TS / deft verbs — no uv/python).
|
|
309
|
+
core:
|
|
310
|
+
taskfile: ./tasks/core.yml
|
|
311
|
+
optional: true
|
|
312
|
+
internal: true
|
|
313
|
+
ci:
|
|
314
|
+
taskfile: ./tasks/ci.yml
|
|
315
|
+
optional: true
|
|
316
|
+
internal: true
|
|
317
|
+
# npm consumer deposits resolve verbs through global `deft` when the vendored
|
|
318
|
+
# packages/cli/dist/bin.js is absent (#2022 Phase 3).
|
|
319
|
+
engine:
|
|
320
|
+
taskfile: ./tasks/engine.yml
|
|
321
|
+
optional: true
|
|
310
322
|
|
|
311
323
|
tasks:
|
|
312
324
|
default:
|
|
@@ -320,14 +332,16 @@ tasks:
|
|
|
320
332
|
desc: "Run the context-appropriate pre-commit gate: full framework self-check in this repo, consumer-safe gate from vendored installs (#1519)."
|
|
321
333
|
dir: '{{.USER_WORKING_DIR}}'
|
|
322
334
|
deps:
|
|
323
|
-
- task:
|
|
335
|
+
- task: engine:_ts-build
|
|
324
336
|
cmds:
|
|
325
|
-
|
|
326
|
-
|
|
337
|
+
- task: engine:invoke
|
|
338
|
+
vars:
|
|
339
|
+
ENGINE_CMD: 'check --framework-root "{{.TASKFILE_DIR}}" --project-root "{{.USER_WORKING_DIR}}"'
|
|
327
340
|
|
|
328
341
|
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)."
|
|
342
|
+
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). Sole wired consumer of maintainer-only core:* / ci:* Python lanes (#2022 Phase 2)."
|
|
330
343
|
deps:
|
|
344
|
+
# Maintainer-only Python lanes (tasks/core.yml) — not on check:consumer.
|
|
331
345
|
- core:validate
|
|
332
346
|
- core:lint
|
|
333
347
|
- core:test
|
|
@@ -359,7 +373,7 @@ tasks:
|
|
|
359
373
|
desc: "Run the consumer-safe Deft quality gate for vendored installs (#1519)."
|
|
360
374
|
deps:
|
|
361
375
|
- doctor
|
|
362
|
-
- toolchain:check
|
|
376
|
+
- toolchain:check-consumer
|
|
363
377
|
- verify:branch
|
|
364
378
|
- verify:cache-fresh
|
|
365
379
|
- verify:wip-cap
|
|
@@ -395,12 +409,11 @@ tasks:
|
|
|
395
409
|
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
410
|
dir: '{{.USER_WORKING_DIR}}'
|
|
397
411
|
deps:
|
|
398
|
-
- task:
|
|
399
|
-
vars:
|
|
400
|
-
DEFT_ROOT: "{{.TASKFILE_DIR}}"
|
|
412
|
+
- task: engine:_ts-build
|
|
401
413
|
cmds:
|
|
402
|
-
|
|
403
|
-
|
|
414
|
+
- task: engine:invoke
|
|
415
|
+
vars:
|
|
416
|
+
ENGINE_CMD: 'validate-strategy-output --project-root "{{.USER_WORKING_DIR}}"'
|
|
404
417
|
|
|
405
418
|
# Pack-projection drift gate (#1294 / #1283, ADR-001). User-facing alias for
|
|
406
419
|
# `packs:verify-drift`, defined at the root Taskfile so it carries the
|
|
@@ -434,40 +447,24 @@ tasks:
|
|
|
434
447
|
# addopts=` reset overrides the pyproject default of `-m 'not slow'`
|
|
435
448
|
# so the `-m slow` selector here actually picks up the marked tests.
|
|
436
449
|
check:slow:
|
|
437
|
-
desc: "Run the @pytest.mark.slow test lane (watchdog regression suite excluded from `task check` by default, #975)"
|
|
450
|
+
desc: "Run the @pytest.mark.slow test lane (watchdog regression suite excluded from `task check` by default, #975). Maintainer-only Python lane — not part of `check:consumer`."
|
|
438
451
|
cmds:
|
|
439
452
|
# `--project` pins uv to the framework root so ancestor pyproject.toml
|
|
440
453
|
# files cannot hijack the resolver via uv's upward walk (#1011).
|
|
441
454
|
- uv --project "{{.TASKFILE_DIR}}" run pytest tests/ -o addopts= -m slow
|
|
442
455
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
|
456
|
+
# Maintainer-only packaging aliases (#2022 Phase 2). `core:*` is internal;
|
|
457
|
+
# these root aliases remain callable for release Step 6 (`task build`) and
|
|
458
|
+
# local maintainer workflows. Not wired into `check:consumer`.
|
|
459
459
|
build:
|
|
460
|
-
desc: Package framework for distribution (alias for core:build)
|
|
460
|
+
desc: Package framework for distribution (maintainer-only; alias for core:build)
|
|
461
461
|
cmds:
|
|
462
462
|
- task: core:build
|
|
463
463
|
clean:
|
|
464
|
-
desc: Clean generated artifacts (alias for core:clean)
|
|
464
|
+
desc: Clean generated artifacts (maintainer-only; alias for core:clean)
|
|
465
465
|
cmds:
|
|
466
466
|
- task: core:clean
|
|
467
|
-
|
|
468
|
-
desc: Validate all markdown files (alias for core:validate)
|
|
469
|
-
cmds:
|
|
470
|
-
- task: core:validate
|
|
467
|
+
|
|
471
468
|
install:
|
|
472
469
|
desc: Install deft (alias for install:install)
|
|
473
470
|
cmds:
|
|
@@ -477,7 +474,7 @@ tasks:
|
|
|
477
474
|
cmds:
|
|
478
475
|
- task: install:uninstall
|
|
479
476
|
# User-facing upgrade entrypoint (#1061). Aliases the install:upgrade
|
|
480
|
-
# wrapper that delegates to
|
|
477
|
+
# wrapper that delegates to the native deft-ts install-upgrade handler. Cited by the doctor's
|
|
481
478
|
# failure prose and docs/install-manifest.md as the canonical
|
|
482
479
|
# post-drift repair entrypoint for the AGENTS.md / manifest /
|
|
483
480
|
# .deft-version triple.
|
|
@@ -485,10 +482,6 @@ tasks:
|
|
|
485
482
|
desc: "Upgrade deft framework -- refresh AGENTS.md + write install manifest + regenerate .deft-version (alias for install:upgrade, #1061)"
|
|
486
483
|
cmds:
|
|
487
484
|
- task: install:upgrade
|
|
488
|
-
stats:
|
|
489
|
-
desc: Show framework statistics (alias for core:stats)
|
|
490
|
-
cmds:
|
|
491
|
-
- task: core:stats
|
|
492
485
|
|
|
493
486
|
# #1272: canonical doctor surface -- thin shim that forwards to
|
|
494
487
|
# ``.deft/core/run doctor``. The ``run`` CLI owns the diagnostic
|
|
@@ -502,16 +495,18 @@ tasks:
|
|
|
502
495
|
# in ``tasks/framework.yml`` now prints a redaction notice pointing
|
|
503
496
|
# the operator at this surface.
|
|
504
497
|
doctor:
|
|
505
|
-
desc: "Canonical doctor surface (#1272) -- task doctor [-- --session | --fix | --json | --quiet].
|
|
498
|
+
desc: "Canonical doctor surface (#1272) -- task doctor [-- --session | --fix | --json | --quiet]. Uses vendored bin.js in source checkouts or global deft on npm consumer deposits (#2022 Phase 3)."
|
|
506
499
|
dir: '{{.USER_WORKING_DIR}}'
|
|
507
|
-
env:
|
|
508
|
-
PYTHONUTF8: "1"
|
|
509
500
|
cmds:
|
|
510
|
-
-
|
|
501
|
+
- task: engine:invoke
|
|
502
|
+
vars:
|
|
503
|
+
ENGINE_CMD: 'doctor --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
511
504
|
|
|
512
505
|
setup:
|
|
513
506
|
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
507
|
dir: '{{.USER_WORKING_DIR}}'
|
|
508
|
+
deps:
|
|
509
|
+
- verify:_ts-build
|
|
515
510
|
env:
|
|
516
511
|
PYTHONUTF8: "1"
|
|
517
512
|
cmds:
|
|
@@ -568,24 +563,19 @@ tasks:
|
|
|
568
563
|
# GitHub CLI cache proxy. Default invocation here passes --check so
|
|
569
564
|
# `task setup` never prompts on a clean re-run; operators wanting to
|
|
570
565
|
# opt in run `task setup:ghx` (defined below) which is the
|
|
571
|
-
# interactive entry point.
|
|
572
|
-
|
|
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
|
|
566
|
+
# interactive entry point. Native TypeScript handler (#2022 Phase 1).
|
|
567
|
+
- node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" setup:ghx --check
|
|
578
568
|
|
|
579
569
|
setup:ghx:
|
|
580
570
|
desc: "Consent-gated ghx (brunoborges/ghx) installer (#884) -- task setup:ghx [-- --yes]"
|
|
581
571
|
dir: '{{.USER_WORKING_DIR}}'
|
|
582
|
-
|
|
583
|
-
|
|
572
|
+
deps:
|
|
573
|
+
- verify:_ts-build
|
|
584
574
|
# Per `conventions/task-caching.md` (#574): no `sources:` / `generates:`
|
|
585
575
|
# because the script forwards user-facing flags via {{.CLI_ARGS}}
|
|
586
576
|
# (notably --yes for non-interactive CI / scripted approval).
|
|
587
577
|
cmds:
|
|
588
|
-
-
|
|
578
|
+
- node "{{.TASKFILE_DIR}}/packages/cli/dist/bin.js" setup:ghx {{.CLI_ARGS}}
|
|
589
579
|
|
|
590
580
|
# Release pipeline tasks (#74 + #716 safety hardening, namespace flatten #718).
|
|
591
581
|
#
|
package/UPGRADING.md
CHANGED
|
@@ -16,7 +16,7 @@ From v0.55.1 onwards `@deftai/directive` is published on npm. The canonical upgr
|
|
|
16
16
|
npm i -g @deftai/directive@latest
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Run from any shell with Node ≥ 20. After upgrading, start a new agent session so the refreshed AGENTS.md and skills load from a clean context. Run `
|
|
19
|
+
Run from any shell with Node ≥ 20. After upgrading, run `deft update` from your project root to refresh the vendored `.deft/core/` payload and project-root `.githooks/` (#2049), then start a new agent session so the refreshed AGENTS.md and skills load from a clean context. Run `deft doctor` to confirm the install state.
|
|
20
20
|
|
|
21
21
|
### One-time migration from the Go installer (legacy → npm)
|
|
22
22
|
|
|
@@ -94,6 +94,7 @@ runs the doctor first gets pointed at this exact two-step before touching `init`
|
|
|
94
94
|
- **From v0.25.x — manual (breaking).** The deft-cache on-disk layout changed: [From v0.25.x → v0.26.0](#from-v025x--v0260-deft-cache-unified-layer-breaking).
|
|
95
95
|
- **From v0.26.x — auto-handled (interactive).** Run the triage adoption ritual: [From v0.26.x → v0.27](#from-v026x---v027-triage-adoption-via-task-triagewelcome).
|
|
96
96
|
- **From v0.27.x — mostly auto-handled.** Pick up the install manifest and the `deft/` → `.deft/core/` layout: [From v0.27.x → v0.28](#from-v027x---v028-canonical-install-manifest-at-installversion), [From deft/ → .deft/core/](#from-deft---deftcore), and [From drifted AGENTS.md → current install](#from-drifted-agentsmd---current-install-task-upgrade-repair-path-1061).
|
|
97
|
+
- **From v0.60.x — manual (hook refresh).** After #2049, consumer `.githooks/` dispatch through the `deft` CLI only. Run [From v0.60.0 → v0.61.x (refresh project-root git hooks, #2049)](#from-v0600--v061x-refresh-project-root-git-hooks-2049) after every framework upgrade that touches hook templates.
|
|
97
98
|
- **From v0.28–v0.36 (and the final hop to current) — auto-handled.** If still on the Go-installer layout, follow the [One-time migration from the Go installer](#one-time-migration-from-the-go-installer-legacy--npm) above, then `npm i -g @deftai/directive@latest` for all future upgrades.
|
|
98
99
|
|
|
99
100
|
**Final step for every bucket.** Finish on the canonical upgrade command, then let the doctor confirm you are current:
|
|
@@ -102,7 +103,22 @@ runs the doctor first gets pointed at this exact two-step before touching `init`
|
|
|
102
103
|
npm i -g @deftai/directive@latest
|
|
103
104
|
```
|
|
104
105
|
|
|
105
|
-
Then run `directive doctor`: it checks install integrity and tells you whether any further hop is still due. If still on a Go-installer layout, follow the [One-time migration from the Go installer](#one-time-migration-from-the-go-installer-legacy--npm) first.
|
|
106
|
+
Then run `deft update` in your project root (refreshes `.deft/core/` and `.githooks/`), then `directive doctor`: it checks install integrity and tells you whether any further hop is still due. If still on a Go-installer layout, follow the [One-time migration from the Go installer](#one-time-migration-from-the-go-installer-legacy--npm) first.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## From v0.60.0 → v0.61.x (refresh project-root git hooks, #2049)
|
|
111
|
+
|
|
112
|
+
- **Applies when:** your project was on deft v0.60.x (or earlier) with `.githooks/` installed via `deft setup` / the npm deposit path, and hooks still invoke legacy Python scripts (`scripts/preflight_branch.py`, `scripts/preflight_gh.py`, etc.). Detection: `deft verify:hooks-installed` fails with "still dispatches through Python scripts (expected deft CLI only, #2049)" or pre-commit/pre-push errors mentioning missing `scripts/*.py` on Python-free installs.
|
|
113
|
+
- **Safe to auto-run:** Yes. `deft update` from the project root re-deposits the current `.githooks/` templates and refreshes the vendored `.deft/core/` payload. No manual hook editing required when the update completes cleanly.
|
|
114
|
+
- **Restart required:** No for hook wiring — but start a **new agent session** after update so AGENTS.md and skills reflect the refreshed managed section.
|
|
115
|
+
- **Commands:**
|
|
116
|
+
- `npm i -g @deftai/directive@latest` (upgrade the global CLI/engine)
|
|
117
|
+
- `deft update` (from project root — refreshes `.deft/core/` + `.githooks/`)
|
|
118
|
+
- `deft verify:hooks-installed` (confirm pre-commit/pre-push dispatch via `deft verify:branch`, `deft verify:encoding`, `deft preflight-gh`)
|
|
119
|
+
- `deft doctor` (install integrity + managed-section freshness)
|
|
120
|
+
|
|
121
|
+
If `deft update` is unavailable (older deposit), fall back to `deft setup` to re-install the hooks path and copy current hook templates.
|
|
106
122
|
|
|
107
123
|
---
|
|
108
124
|
|
|
@@ -318,7 +334,7 @@ The relocator does NOT auto-rewrite consumer-owned files (the canonical reason:
|
|
|
318
334
|
- `AGENTS.md` head/tail (above and below the managed-section markers) -- replace `deft/run` with `.deft/core/run` and `Full guidelines: deft/main.md` with `Full guidelines: .deft/core/main.md`.
|
|
319
335
|
- CI workflow files (`.github/workflows/*.yml`) -- replace any `deft/run <task>` invocations.
|
|
320
336
|
- Project scripts (`scripts/`, `Makefile`, `Taskfile.yml`, dotfiles) that hardcode the legacy path.
|
|
321
|
-
- README / docs / contributor-onboarding prose that points new contributors at `deft/run`
|
|
337
|
+
- README / docs / contributor-onboarding prose that points new contributors at `directive bootstrap` for first-time setup (replaces legacy `deft/run bootstrap` / `run project` / `run spec` shims).
|
|
322
338
|
|
|
323
339
|
The advisory grep output is the operator's worklist; treat it as a finite todo. Once every flagged occurrence is either updated to `.deft/core/run` or explicitly acknowledged as legacy-friendly redirect-stub content (e.g. the `skills/deft-{sync,setup,...}/SKILL.md` redirect stubs that intentionally retain `deft/run` per [#411](https://github.com/deftai/directive/issues/411)), commit the changes alongside the relocate. (F1 #1015)
|
|
324
340
|
|
|
Binary file
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# The Directive Lifecycle (Conceptual Overview)
|
|
2
|
+
|
|
3
|
+
A single-picture mental model of how Deft Directive turns an idea into shipped,
|
|
4
|
+
auditable work — and keeps doing so as the project grows. It is **not** a one-and-done
|
|
5
|
+
pipeline; it is two connected phases that loop.
|
|
6
|
+
|
|
7
|
+
> **See also**: [getting-started.md](./getting-started.md) | [commands.md](../commands.md) | [strategies/README.md](../strategies/README.md) | [CONCEPTS.md](../../docs/CONCEPTS.md) | [ARCHITECTURE.md](../../docs/ARCHITECTURE.md)
|
|
8
|
+
>
|
|
9
|
+
> The `CONCEPTS.md` / `ARCHITECTURE.md` links resolve in the framework source repo; in an installed `.deft/core/docs/` they are maintainer-side references that may not be present.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
> This diagram is a **conceptual overview**, not a command reference. The bubble labels are
|
|
14
|
+
> plain-language stages; the [stage → real surface](#stage--real-surface) table below maps
|
|
15
|
+
> each one to the actual strategy, skill, or `task` command that implements it.
|
|
16
|
+
|
|
17
|
+
## The two phases
|
|
18
|
+
|
|
19
|
+
### 1. At inception (run once, re-run as needed)
|
|
20
|
+
|
|
21
|
+
A project starts with a **Concept**. That concept passes through **Strategy Analysis** — an
|
|
22
|
+
iterative loop of *looking* at the terrain and *deep thinking* about the approach — until it
|
|
23
|
+
produces a **Specification + Artifacts** (the project definition and the first proposed scope
|
|
24
|
+
vBRIEFs).
|
|
25
|
+
|
|
26
|
+
Strategy analysis is deliberately a loop, not a step: you can map, then probe, then discuss,
|
|
27
|
+
then map again before the spec stabilizes. It is also re-entered later "as needed" when a piece
|
|
28
|
+
of work turns out to be big or fuzzy enough to need rethinking rather than just refining.
|
|
29
|
+
|
|
30
|
+
### 2. Resume (the usual entry, every session)
|
|
31
|
+
|
|
32
|
+
Once a specification exists, the everyday on-ramp is **Session Start** — the session-start
|
|
33
|
+
ritual answering "what's next?". From there work flows through the queue:
|
|
34
|
+
|
|
35
|
+
- **Triage + Refine/Rethink** — the queue of candidate work. New **issues** and **features**
|
|
36
|
+
both enter here. Each item is either sliced forward, or — when it needs more thought —
|
|
37
|
+
escalated back up to Strategy Analysis (the *rethink* path).
|
|
38
|
+
- **Slice** — break refined scope into independently-grabbable vertical slices.
|
|
39
|
+
- **Swarm** — dispatch parallel agents against the sliced stories.
|
|
40
|
+
- **Review/Fix** — a tight, skill-driven loop that resolves reviewer findings until the work is
|
|
41
|
+
merge-ready. Review comes **after** the swarm, not before.
|
|
42
|
+
- **Ship** — merge and release.
|
|
43
|
+
|
|
44
|
+
Shipping is not the end: it **surfaces new issues and features**, which flow back into the
|
|
45
|
+
Triage queue. The specification and artifacts produced at inception also feed proposed scopes
|
|
46
|
+
into the same queue. Every pass is iterative.
|
|
47
|
+
|
|
48
|
+
## Stage → real surface
|
|
49
|
+
|
|
50
|
+
The diagram's labels are conceptual. Here is what each one actually corresponds to in the
|
|
51
|
+
framework:
|
|
52
|
+
|
|
53
|
+
| Diagram label | What it really is |
|
|
54
|
+
|---|---|
|
|
55
|
+
| **Concept** | The initial idea / project framing — entry into [`deft-directive-setup`](../skills/deft-directive-setup/SKILL.md) or a `/deft:change`. |
|
|
56
|
+
| **Look** | Mapping and exploring the terrain — [`strategies/map.md`](../strategies/map.md) (`/deft:run:map`), codebase structure. |
|
|
57
|
+
| **Deep Think** | Adversarial / alignment analysis — [`strategies/probe.md`](../strategies/probe.md), [`strategies/discuss.md`](../strategies/discuss.md), [`strategies/research.md`](../strategies/research.md), and `deft-directive-gh-arch`. |
|
|
58
|
+
| **Strategy Analysis** | The preparatory strategies cycling through the [strategy chaining gate](../strategies/README.md) before spec generation. |
|
|
59
|
+
| **Spec / Specification + Artifacts** | Output of the spec-generating strategies (interview, speckit, …): `vbrief/PROJECT-DEFINITION.vbrief.json` plus dated `vbrief/proposed/` scope vBRIEFs. |
|
|
60
|
+
| **Resume / Session Start** | The session-start ritual — `task session:start` and the `task triage:welcome` "what's next" one-liner. |
|
|
61
|
+
| **Triage + Refine/Rethink** | The triage cache and refinement loop — `task triage:*`, [`deft-directive-triage`](../skills/deft-directive-triage/SKILL.md), [`deft-directive-refinement`](../skills/deft-directive-refinement/SKILL.md). "Rethink" = escalate back to Strategy Analysis. |
|
|
62
|
+
| **Slice** | Vertical-slice decomposition — [`deft-directive-gh-slice`](../skills/deft-directive-gh-slice/SKILL.md) and [`deft-directive-decompose`](../skills/deft-directive-decompose/SKILL.md). |
|
|
63
|
+
| **Swarm** | Parallel local agent orchestration — [`deft-directive-swarm`](../skills/deft-directive-swarm/SKILL.md), `task swarm:*`. |
|
|
64
|
+
| **Review/Fix** | Bot-reviewer response loop — [`deft-directive-review-cycle`](../skills/deft-directive-review-cycle/SKILL.md) and [`deft-directive-pre-pr`](../skills/deft-directive-pre-pr/SKILL.md). |
|
|
65
|
+
| **Ship** | PR merge and release — `task pr:*` and [`deft-directive-release`](../skills/deft-directive-release/SKILL.md). |
|
|
66
|
+
| **Issues / Features** | GitHub issues and feature requests mirrored into `.deft-cache/` and surfaced as triage candidates. |
|
|
67
|
+
|
|
68
|
+
## Why it loops
|
|
69
|
+
|
|
70
|
+
The central claim of the picture is that Directive is **reiterative**. Strategy analysis is
|
|
71
|
+
front-loaded but re-entrant. Triage either slices work forward or rethinks it. Review/fix
|
|
72
|
+
cycles until merge-ready. And shipping generates the next round of issues and features. The
|
|
73
|
+
framework is built to be re-entered every session, not walked once.
|
package/docs/getting-started.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Deft Directive is a Taskfile-first framework for AI-assisted software work. It combines agent guidance, deterministic gates, vBRIEF lifecycle metadata, installer/doctor handoff, and cache-backed backlog workflows. This guide walks through installation, preferences, project setup, and the first scope workflow.
|
|
4
4
|
|
|
5
|
-
> **Note**: This guide is an orientation layer. For
|
|
5
|
+
> **Note**: This guide is an orientation layer. For a single-picture mental model of how Directive turns an idea into shipped work, see [the Directive lifecycle](./directive-lifecycle.md); for command behavior, see [commands.md](../commands.md); for current architecture details, see [ARCHITECTURE.md](../../docs/ARCHITECTURE.md).
|
|
6
|
+
|
|
7
|
+
## The shape of the workflow
|
|
8
|
+
|
|
9
|
+
Before the mechanics below, it helps to see the whole loop. Directive is two connected phases that repeat: an **inception** phase (Concept → Strategy Analysis → Specification + Artifacts) that feeds a recurring **per-session** phase (Session Start → Triage/Refine → Slice → Swarm → Review/Fix → Ship), where shipping surfaces new issues and features that flow back into the queue. The full picture, with a stage-to-real-command mapping table, lives in [the Directive lifecycle overview](./directive-lifecycle.md).
|
|
6
10
|
|
|
7
11
|
## Deft & Directive (naming)
|
|
8
12
|
|