@deftai/directive-content 0.107.0 → 0.108.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/Taskfile.yml +1 -1
- package/UPGRADING.md +22 -3
- package/commands.md +24 -2
- package/contracts/design-critique.md +117 -16
- package/docs/delivery-attempt.md +2 -1
- package/docs/freshness-contract.md +6 -1
- package/docs/getting-started.md +10 -11
- package/docs/hook-runtime-unavailable.md +54 -0
- package/docs/orphan-active-verdict-basis.md +166 -0
- package/package.json +1 -1
- package/packs/skills/skills-pack-0.1.json +7 -7
- package/scm/github.md +31 -1
- package/skills/deft-directive-build/SKILL.md +1 -1
- package/skills/deft-directive-cost/SKILL.md +7 -11
- package/skills/deft-directive-design-critique/SKILL.md +8 -1
- package/skills/deft-directive-design-critique/references/motion-shape.md +19 -0
- package/skills/deft-directive-interview/SKILL.md +10 -10
- package/skills/deft-directive-release/SKILL.md +10 -6
- package/skills/deft-directive-review-cycle/SKILL.md +33 -0
- package/skills/deft-directive-setup/SKILL.md +53 -22
- package/skills/deft-directive-swarm/references/core-ops.md +4 -0
- package/skills/deft-directive-swarm/references/core-phase-1-2.md +1 -1
- package/skills/deft-directive-swarm/references/core-phase-3.md +3 -1
- package/skills/deft-directive-swarm/references/core-phase-4.md +11 -8
- package/skills/deft-directive-swarm/references/host-cursor.md +1 -0
- package/skills/deft-directive-swarm/references/host-grok-build.md +1 -0
- package/tasks/engine.yml +2 -0
- package/tasks/occupancy.yml +24 -2
- package/tasks/prd.yml +4 -5
- package/tasks/session.yml +3 -3
- package/tasks/toolchain.yml +2 -2
- package/tasks/verify.yml +11 -1
- package/templates/agent-prompt-preamble.md +9 -2
- package/templates/agents-entry.md +6 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# `verify:orphan-active`: verdict basis and freshness (#3767)
|
|
2
|
+
|
|
3
|
+
`verify:orphan-active` decides whether an `xbrief/active/` brief with
|
|
4
|
+
`plan.status == running` is really still live work. Until #3767 it answered
|
|
5
|
+
that question from a triage-cache hit returned **unconditionally** — no age
|
|
6
|
+
bound, no re-validation. A cached `open` written twelve hours earlier beat
|
|
7
|
+
reality and suppressed the live read that would have corrected it, so the gate
|
|
8
|
+
exited 0 while scanning the very brief whose issue had already closed.
|
|
9
|
+
|
|
10
|
+
This document records what the gate now does, why, and what it still cannot
|
|
11
|
+
promise.
|
|
12
|
+
|
|
13
|
+
Legend (RFC2119): `!`=MUST, `~`=SHOULD, `⊗`=MUST NOT, `?`=MAY.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Two modes, split by query shape
|
|
18
|
+
|
|
19
|
+
The gate has two callers with different obligations, so it has two mechanisms.
|
|
20
|
+
|
|
21
|
+
| | Scoped `--issue N` | Unscoped aggregate |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Caller | after-merge DONE proof (#3429 / #3476) | `task check`, pre-commit, pre-push sweep |
|
|
24
|
+
| Mechanism | authoritative per-issue REST read | one complete open-issue inventory |
|
|
25
|
+
| N | 1 | one call regardless of brief count |
|
|
26
|
+
| Unknown state | **fail closed** (exit 1, `unresolved`) | **fail open** (exit 0, reported `unverified`) |
|
|
27
|
+
| Latency budget | 5 s | 15 s |
|
|
28
|
+
|
|
29
|
+
The unknown asymmetry is deliberate and predates this change. Scoped is a proof
|
|
30
|
+
obligation before a worker claims DONE about one named origin. The aggregate
|
|
31
|
+
sweep must not make offline work network-authorized — hard-failing every
|
|
32
|
+
aggregate unknown would break `--skip-gh`, offline runs, and fresh clones.
|
|
33
|
+
|
|
34
|
+
⊗ Do not flatten the two unknown policies into one rule.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The freshness choice
|
|
39
|
+
|
|
40
|
+
**Age bound plus re-validation, applied per mode.** Both options offered by
|
|
41
|
+
#3767 are used, because each mode needs a different one.
|
|
42
|
+
|
|
43
|
+
- A cache hit is honoured only when it is at most **15 minutes** old
|
|
44
|
+
(`ISSUE_CACHE_MAX_AGE_MS`). Older entries are not evidence.
|
|
45
|
+
- Scoped `--issue N` re-validates first: it takes the authoritative read and
|
|
46
|
+
falls back to the cache only inside the age bound, when the live read is
|
|
47
|
+
unavailable. Unknown after that is `unresolved`.
|
|
48
|
+
- The aggregate sweep resolves from the open-issue inventory when the network
|
|
49
|
+
is allowed, and uses an in-bound cache hit only under `--skip-gh` or when the
|
|
50
|
+
inventory itself is unavailable.
|
|
51
|
+
|
|
52
|
+
15 minutes keeps a warm-cache offline run working while making an overnight
|
|
53
|
+
entry non-authoritative — the measured entry was roughly twelve hours old.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## The aggregate inventory
|
|
58
|
+
|
|
59
|
+
The sweep reuses `restIssueListOpenInventory` (#3752): one
|
|
60
|
+
`gh api --paginate --slurp repos/<owner>/<repo>/issues?state=open&per_page=100`
|
|
61
|
+
subprocess. It excludes pull-request rows and **fails closed** on command
|
|
62
|
+
failure, non-JSON output, a non-array payload, a malformed row, buffer
|
|
63
|
+
exhaustion, and the pagination cap.
|
|
64
|
+
|
|
65
|
+
! The inventory MUST be complete. `probeCacheDrift`'s helper defaults to a
|
|
66
|
+
1,000-item limit; reusing that capped set as a closed-state oracle would
|
|
67
|
+
misclassify open issue 1001+ in a larger repository.
|
|
68
|
+
|
|
69
|
+
Membership in a successful inventory means open. **Absence means "not open"**,
|
|
70
|
+
which is the direction that tells an operator to run `scope:complete` on what
|
|
71
|
+
may be live work — so absence is confirmed by one authoritative per-issue read
|
|
72
|
+
before the gate acts on it. That confirming result is reused for the rest of
|
|
73
|
+
the run when several briefs name the same issue. In the ordinary case
|
|
74
|
+
(everything open) that costs zero extra calls.
|
|
75
|
+
|
|
76
|
+
When the inventory is unavailable the gate reports `unverified` rather than
|
|
77
|
+
inferring closed. Fail-closed here means never manufacturing a false "closed",
|
|
78
|
+
not turning the sweep into a connectivity check.
|
|
79
|
+
|
|
80
|
+
### Why not a live read per brief
|
|
81
|
+
|
|
82
|
+
Per-brief live reads are the mechanism #3752 removed. Measured: the inventory
|
|
83
|
+
is **4.2 s constant**, against **14.2 s** and **76.6 s** for sequential
|
|
84
|
+
per-brief reads at the WIP cap of 20 on two different hosts. Crossover is about
|
|
85
|
+
5 briefs on `gh` and about 1 on `ghx`. `verify:orphan-active` sits in the
|
|
86
|
+
fast-preflight tier, where wall clock rather than REST quota is the constraint.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Reported basis
|
|
91
|
+
|
|
92
|
+
Every run now says how it decided, so a verified pass is distinguishable from
|
|
93
|
+
an unverified one:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
verify:orphan-active: no orphaned active/running xBRIEFs (scanned 3 running briefs in active/).
|
|
97
|
+
Basis: inventory 2, cache 1 (max age 4m).
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
verify:orphan-active: no orphaned active/running xBRIEFs (scanned 1 running brief in active/).
|
|
102
|
+
Basis: unverified 1.
|
|
103
|
+
UNVERIFIED: state could not be established for the references below, so this run is
|
|
104
|
+
not evidence that they are unshipped:
|
|
105
|
+
- #8001 (open-issue inventory unavailable: gh api failed: ...)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`EvaluateResult.basis` carries the same counts structurally
|
|
109
|
+
(`inventory`, `live`, `cache`, `unverified`, `maxCacheAgeMs`, `proxied`,
|
|
110
|
+
`elapsedMs`, `budgetMs`).
|
|
111
|
+
|
|
112
|
+
⊗ Do not cite an exit 0 with `unverified > 0` as evidence that a tree is clean.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## The `ghx` caveat
|
|
117
|
+
|
|
118
|
+
"Live" is itself a cache. `defaultRunGh` resolves through `resolveBinary()`,
|
|
119
|
+
which prefers **`ghx`**, a cached read-only GET proxy whose age nothing in this
|
|
120
|
+
gate can inspect.
|
|
121
|
+
|
|
122
|
+
This gate therefore **pins plain `gh`** for its authoritative reads when `gh` is
|
|
123
|
+
on PATH. When only `ghx` is available the gate still runs, sets
|
|
124
|
+
`basis.proxied`, and prints:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
Note: reads resolved through `ghx`, a cached GET proxy; freshness is bounded by that
|
|
128
|
+
proxy, which this gate cannot inspect (#3737).
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
⊗ Do not claim the gate detects a closed origin "regardless of cache age" while
|
|
132
|
+
`ghx` is in the path. Whether `resolveBinary` should prefer `ghx` at all is
|
|
133
|
+
[#3737](https://github.com/deftai/directive/issues/3737).
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Latency budgets
|
|
138
|
+
|
|
139
|
+
There were none before #3767, which is why "affordable" was unfalsifiable.
|
|
140
|
+
|
|
141
|
+
| Mode | Budget | Basis |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| Scoped `--issue N` | 5 s | one issue read plus at most one linked-PR read, measured ~0.75 s each |
|
|
144
|
+
| Unscoped aggregate | 15 s | one 4.2 s inventory plus confirming reads for apparent closes |
|
|
145
|
+
|
|
146
|
+
Exceeding a budget prints an advisory line and does **not** change the exit
|
|
147
|
+
code. Budget drift is a signal to re-measure the mechanism, not a new failure
|
|
148
|
+
mode for callers.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Out of scope
|
|
153
|
+
|
|
154
|
+
- The offline crash when neither `gh` nor `ghx` is on PATH
|
|
155
|
+
([#3774](https://github.com/deftai/directive/issues/3774)).
|
|
156
|
+
- Whether `resolveBinary` should prefer `ghx`
|
|
157
|
+
([#3737](https://github.com/deftai/directive/issues/3737)).
|
|
158
|
+
- The `cache_fresh` forge-error fail-open decided on
|
|
159
|
+
[#3738](https://github.com/deftai/directive/issues/3738).
|
|
160
|
+
|
|
161
|
+
## Related
|
|
162
|
+
|
|
163
|
+
- [#3429](https://github.com/deftai/directive/issues/3429) — the gate's contract
|
|
164
|
+
- [#3476](https://github.com/deftai/directive/issues/3476) — `verify:completed-tracked`
|
|
165
|
+
- [#3752](https://github.com/deftai/directive/issues/3752) — the open-inventory mechanism reused here
|
|
166
|
+
- [#3156](https://github.com/deftai/directive/issues/3156) — gate integrity; this was a deliberate gate-definition change
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive-content",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.0",
|
|
4
4
|
"deftConsumerDeposit": true,
|
|
5
5
|
"description": "Shippable Directive framework content in the consumer .deft/core/ layout (C1 flatten), plus the engine surfaces (.githooks/, Taskfile.yml, tasks/) the deposit wires. Python-free per #2022 Phase 3. Refs #11, #1669, #1967.",
|
|
6
6
|
"license": "MIT",
|