@agentsfleet/orly 0.10.6 → 0.10.8
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/AGENTS.md +7 -7
- package/SOUL.md +2 -2
- package/audits/agents-md.md +1 -1
- package/audits/doc-read.sh +97 -16
- package/audits/msid-ui.sh +57 -13
- package/core/operating-model.md +5 -5
- package/dispatch/lib.sh +2 -2
- package/dispatch/write_any.md +6 -6
- package/dispatch/write_any.sh +1 -1
- package/dispatch/write_sql.md +8 -6
- package/dispatch/write_sql.sh +2 -2
- package/docs/SCHEMA_CONVENTIONS.md +1 -1
- package/docs/greptile-learnings/RULES.md +15 -15
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -10,13 +10,13 @@ You are this repository's coding agent: deterministic, autonomous, command-line-
|
|
|
10
10
|
|
|
11
11
|
**Tone.** Be properly funny — human-funny, dry, actually landing; not a bot doing bits. Swear words are absolutely fine. Never trade technical clarity for either.
|
|
12
12
|
|
|
13
|
-
**Start:** `SOUL.md` (
|
|
13
|
+
**Start:** `SOUL.md` (Aiwa's working notes) is inlined as the final section; re-read it when padding or burying the answer.
|
|
14
14
|
|
|
15
15
|
## Owner & Style
|
|
16
16
|
|
|
17
|
-
**The human is Kishore** — casual handle **Indy**; either name, any case, addresses him. Ambiguous "the user" / "they" here = Kishore. The agent is **Oracle**, casual handle **
|
|
17
|
+
**The human is Kishore** — casual handle **Indy**; either name, any case, addresses him. Ambiguous "the user" / "they" here = Kishore. The agent is **Oracle**, casual handle **Aiwa**. `orly` names the agentsfleet CLI only (`orly gate`, `orly init`, `orly update`, and the `Orly-Override` trailer it writes).
|
|
18
18
|
|
|
19
|
-
**Address tags.** Kishore: **🤠 Indy**; agent: **🦉
|
|
19
|
+
**Address tags.** Kishore: **🤠 Indy**; agent: **🦉 Aiwa** (`Oracle`). **Project name:** `agentsfleet` (domains → `agentsfleet.net`). Write product as `agentsfleet` (inline code), never bare; stale legacy-brand reps → flag, replace when in scope, inform Indy. Products: `agentsfleet` / `agentsfleetd` / `agentsfleet-runner`; entities/API: `fleet`, `fleet_id`, `/fleets`, `core.fleet_*`. Keep: `agentsfleet.dev`, `github.com/agentsfleet/agentsfleet`, `@agentsfleet/*`, `~/Projects/agentsfleet`.
|
|
20
20
|
|
|
21
21
|
MacBook. Languages: Python, Go, Rust, TypeScript, Zig. Tooling: `mise` first, `brew` fallback. Forges: `gh`/`glab`. Commit identity from `git config`, never here.
|
|
22
22
|
|
|
@@ -126,7 +126,7 @@ Guards fire pre-hoc regardless of lifecycle stage. Override: `<GATE>: SKIPPED pe
|
|
|
126
126
|
|
|
127
127
|
**Dispatch index — full rule prose in each `dispatch/<entry>.md` façade. Read the façade when its trigger fires — sectioned: scan headers, read the sections the diff touches.** Trigger-surface extensions: `*.zig`, `*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.py`, `*.rs`, `*.go`, `*.sh`, `*.sql`, `*.mdx`, and public OpenAPI prose. Latent `.md` per entry, deterministic `.sh` where mechanisable. Signals: 🟢 pass · 🟠 warn · 🔴 fail · 🛑 blocked · 🔥 critical · 🤔 judgment-only · 🟣 delegated. Output glyphs: 🧲 eval · 🛍️ evidence · 👮 security · ⛈️ rule · 💡 info · 📌 note. The router below **is** the gate set.
|
|
128
128
|
|
|
129
|
-
**Legacy-workaround family** — four rules together: **RULE NDC** (no dead code at write time, `docs/greptile-learnings/RULES.md`), **RULE NLR** (touch-it-fix-it cleanup), **RULE NLG** (no new legacy framing pre-`
|
|
129
|
+
**Legacy-workaround family** — four rules together: **RULE NDC** (no dead code at write time, `docs/greptile-learnings/RULES.md`), **RULE NLR** (touch-it-fix-it cleanup), **RULE NLG** (no new legacy framing pre-`0.30.0`), **Legacy-Design Consult Guard** (user A/B/C consult before patching/keeping/testing legacy). **No compatibility aliases** — old verbs, flag aliases, route wrappers, env aliases, fallback spellings — unless the user explicitly asks in-session.
|
|
130
130
|
|
|
131
131
|
| Trigger — when you… | Dispatch | Latent façade carries · override |
|
|
132
132
|
|---|---|---|
|
|
@@ -197,7 +197,7 @@ Required: one-paragraph goal · explicit assumptions · file/task impact list ·
|
|
|
197
197
|
### EXECUTE
|
|
198
198
|
|
|
199
199
|
Read what the selected dispatch names — **sectioned, not whole-file**: scan headers (`grep -nE "^##+ "`), read the sections the diff shape touches, cite them.
|
|
200
|
-
The full `agentsfleet` trigger map lives in `docs/EXECUTE_DOC_READS.md`. At EXECUTE start read the **Rule-code gloss legend** of `docs/greptile-learnings/RULES.md` plus the sections the spec's "Applicable Rules" names — never the full file. On sub-task shape change, section-scan (`grep -n "^## "`) and re-read only the sections the new shape touches. DOC READ GATE emits one `📖 DOC READ: <path>` proof-line **per triggered document per turn** before the turn's first triggering edit, citing the applied section or a cited skip; auto-mode and prior-turn reads never excuse it. **Record it, don't just claim it:** `bash audits/doc-read.sh log <path
|
|
200
|
+
The full `agentsfleet` trigger map lives in `docs/EXECUTE_DOC_READS.md`. At EXECUTE start read the **Rule-code gloss legend** of `docs/greptile-learnings/RULES.md` plus the sections the spec's "Applicable Rules" names — never the full file. On sub-task shape change, section-scan (`grep -n "^## "`) and re-read only the sections the new shape touches. DOC READ GATE emits one `📖 DOC READ: <path>` proof-line **per triggered document per turn** before the turn's first triggering edit, citing the applied section or a cited skip; auto-mode and prior-turn reads never excuse it. **Record it, don't just claim it:** `bash audits/doc-read.sh log <path> "<section applied>"` — any runtime; Claude Code's Read hook does it for you; pre-commit compares the record to the staged diff. **Log each page as you read it, and cite the section**: a loop writes the same rows, and once did — nine façades in one second, `check` green, violations from a section nobody opened. `check` counts citations and names any bulk second.
|
|
201
201
|
|
|
202
202
|
Edit only approved scope; no opportunistic refactors. Stay in active worktree. Cross-repo writes to `~/Projects/docs/` need explicit per-session ask.
|
|
203
203
|
|
|
@@ -251,9 +251,9 @@ Required when spec involved — after last COMMIT, before PR. Also runs when par
|
|
|
251
251
|
|
|
252
252
|
---
|
|
253
253
|
|
|
254
|
-
# SOUL.md —
|
|
254
|
+
# SOUL.md — Aiwa's working notes
|
|
255
255
|
|
|
256
|
-
> First-person:
|
|
256
|
+
> First-person: Aiwa to future Aiwa. `AGENTS.md` carries the rules; this file
|
|
257
257
|
> carries the judgment — how Indy decides, what he accepts, what he rejects.
|
|
258
258
|
> In force every session; standing orders, not suggestions. Re-read when
|
|
259
259
|
> padding or burying the answer.
|
package/SOUL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- oracle-packs:start persona.indy -->
|
|
2
|
-
# SOUL.md —
|
|
2
|
+
# SOUL.md — Aiwa's working notes
|
|
3
3
|
|
|
4
|
-
> First-person:
|
|
4
|
+
> First-person: Aiwa to future Aiwa. `AGENTS.md` carries the rules; this file
|
|
5
5
|
> carries the judgment — how Indy decides, what he accepts, what he rejects.
|
|
6
6
|
> In force every session; standing orders, not suggestions. Re-read when
|
|
7
7
|
> padding or burying the answer.
|
package/audits/agents-md.md
CHANGED
|
@@ -175,7 +175,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
|
|
|
175
175
|
|
|
176
176
|
| # | Question | Expected |
|
|
177
177
|
|---|---|---|
|
|
178
|
-
| 11.1 | Pre-
|
|
178
|
+
| 11.1 | Pre-v0.30.0, is the table-removal flow rm-file + rm-embed + rm-migration-array (no `ALTER TABLE`/`DROP TABLE`/`SELECT 1;` markers)? | YES |
|
|
179
179
|
| 11.2 | Are static strings in SQL schema a **no-override** ban across every literal that names a value or identifier the application also names — `DEFAULT`, `CHECK (col IN (…))`, trigger-body comparisons against a column, `current_setting()` parameter names, and `RAISE EXCEPTION` text a caller matches on — not just `DEFAULT`/`CHECK`? | YES |
|
|
180
180
|
|
|
181
181
|
### Scenario 12 — Auto-mode boundary (added)
|
package/audits/doc-read.sh
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# doc-read.sh — turn the 📖 DOC READ proof-line into a set comparison.
|
|
3
3
|
#
|
|
4
|
-
# audits/doc-read.sh log <path> record that a file was read
|
|
5
|
-
# audits/doc-read.sh check
|
|
4
|
+
# audits/doc-read.sh log <path> [section] record that a file was read
|
|
5
|
+
# audits/doc-read.sh check staged source vs recorded reads
|
|
6
6
|
#
|
|
7
7
|
# The DOC READ GATE asks an agent to read the façade its edit triggers, and
|
|
8
8
|
# then asks the same agent whether it did. That is a claim about itself
|
|
9
9
|
# compared against nothing. `log` records the read and `check` compares the
|
|
10
10
|
# record against the façades the staged files trigger.
|
|
11
11
|
#
|
|
12
|
+
# `log` is still an assertion, and a loop can make nine of them in one second.
|
|
13
|
+
# That happened: an agent ran `log` over its whole trigger list before opening
|
|
14
|
+
# most of the pages, `check` reported green, and two rule violations reached the
|
|
15
|
+
# diff from a section it had skipped. Two things answer it, and neither can
|
|
16
|
+
# block, because neither is provable:
|
|
17
|
+
#
|
|
18
|
+
# - The optional `section` argument records WHAT the read applied — "§Error
|
|
19
|
+
# discipline: composed with #[from]". A loop cannot produce that line; only
|
|
20
|
+
# reading can. `check` reports how many triggered façades carry one.
|
|
21
|
+
# - Rows for different façades sharing one timestamp are reported as a bulk
|
|
22
|
+
# assertion. A read hook fires per read and spreads across seconds; a
|
|
23
|
+
# scripted loop lands them together. An agent that genuinely read three
|
|
24
|
+
# short pages inside one second is possible too, which is exactly why this
|
|
25
|
+
# is a number in the output and never a red.
|
|
26
|
+
#
|
|
27
|
+
# Partial mechanisation stated honestly beats a red that means nothing — the
|
|
28
|
+
# same argument the missing-record branch below already makes.
|
|
29
|
+
#
|
|
12
30
|
# NOTHING HERE MAY DEPEND ON AN AGENT RUNTIME. `log` is a shell command any
|
|
13
31
|
# agent can run; a runtime that also has a read hook (Claude Code today) can
|
|
14
32
|
# call it automatically, and a runtime that removes that feature tomorrow
|
|
@@ -37,7 +55,12 @@ source "$HERE/rule-ledger-lib.sh"
|
|
|
37
55
|
MODE_LOG="log"
|
|
38
56
|
MODE_CHECK="check"
|
|
39
57
|
LOG_RELATIVE_PATH="orly/doc-reads.jsonl"
|
|
40
|
-
USAGE="usage: $0 log <path> | $0 check"
|
|
58
|
+
USAGE="usage: $0 log <path> [section] | $0 check"
|
|
59
|
+
|
|
60
|
+
# How many façades recorded in one second read as a loop rather than as reading.
|
|
61
|
+
# Two is a plausible pair of short pages; three in the same second is a list
|
|
62
|
+
# being walked.
|
|
63
|
+
BULK_ASSERTION_THRESHOLD=3
|
|
41
64
|
|
|
42
65
|
if [[ -t 1 ]]; then G=$'\033[32m'; R=$'\033[31m'; Y=$'\033[33m'; X=$'\033[0m'
|
|
43
66
|
else G=''; R=''; Y=''; X=''; fi
|
|
@@ -65,7 +88,7 @@ repo_relative() {
|
|
|
65
88
|
# invocation is why two agents in two sessions cannot corrupt each other: the
|
|
66
89
|
# order rows land in does not change which paths the set contains.
|
|
67
90
|
run_log() {
|
|
68
|
-
local path="$1" relative log blob
|
|
91
|
+
local path="$1" section="${2:-}" relative log blob
|
|
69
92
|
relative="$(repo_relative "$path")" || return 0
|
|
70
93
|
[ -n "$relative" ] || return 0
|
|
71
94
|
log="$(read_log_path)" || return 0
|
|
@@ -75,7 +98,11 @@ run_log() {
|
|
|
75
98
|
# Recording it would let two failures compare equal and validate a read of a
|
|
76
99
|
# file that is no longer there.
|
|
77
100
|
[ -n "$blob" ] || return 0
|
|
78
|
-
|
|
101
|
+
# The section rides the SAME row rather than a second file: a citation that
|
|
102
|
+
# could be written without a read beside it would be a third assertion to
|
|
103
|
+
# reconcile, and the pair is what carries meaning.
|
|
104
|
+
printf '{"ts":%s,"path":"%s","blob":"%s","section":"%s"}\n' \
|
|
105
|
+
"$(date +%s)" "$(json_escape "$relative")" "$blob" "$(json_escape "$section")" >> "$log"
|
|
79
106
|
return 0
|
|
80
107
|
}
|
|
81
108
|
|
|
@@ -115,22 +142,43 @@ json_unescape() {
|
|
|
115
142
|
printf '%s' "$1" | sed -e 's/\\"/"/g' -e 's/\\\\/\\/g'
|
|
116
143
|
}
|
|
117
144
|
|
|
118
|
-
# Paths whose recorded read saw the content that is on disk now
|
|
119
|
-
#
|
|
120
|
-
# else, so it does not count — and
|
|
121
|
-
# no blob, cannot prove anything
|
|
145
|
+
# Paths whose recorded read saw the content that is on disk now, one
|
|
146
|
+
# `path<TAB>ts<TAB>section` row each. A row written against an older version of
|
|
147
|
+
# the document proves the agent read something else, so it does not count — and
|
|
148
|
+
# rows from before this milestone, which carry no blob, cannot prove anything
|
|
149
|
+
# and are ignored.
|
|
150
|
+
#
|
|
151
|
+
# The path is cut at the first `","blob":"` rather than by stripping a fixed
|
|
152
|
+
# tail: the row gained a trailing `section` field, and a suffix strip that
|
|
153
|
+
# spelled the old shape would have silently yielded a path that matches nothing
|
|
154
|
+
# — reading as "never read" for every document.
|
|
122
155
|
current_reads() {
|
|
123
|
-
local log="$1" line path blob
|
|
156
|
+
local log="$1" line path blob ts section
|
|
124
157
|
while IFS= read -r line; do
|
|
125
158
|
case "$line" in *'"blob":"'*) ;; *) continue ;; esac
|
|
126
|
-
blob="${line
|
|
159
|
+
blob="${line#*\"blob\":\"}"; blob="${blob%%\"*}"
|
|
127
160
|
[ -n "$blob" ] || continue
|
|
128
|
-
path="${line#*\"path\":\"}"; path="${path
|
|
161
|
+
path="${line#*\"path\":\"}"; path="${path%%\",\"blob\":\"*}"
|
|
129
162
|
path="$(json_unescape "$path")"
|
|
130
|
-
|
|
163
|
+
ts="${line#*\"ts\":}"; ts="${ts%%,*}"
|
|
164
|
+
section=""
|
|
165
|
+
case "$line" in
|
|
166
|
+
*'"section":"'*) section="${line#*\"section\":\"}"; section="${section%%\"*}" ;;
|
|
167
|
+
esac
|
|
168
|
+
[ "$blob" = "$(content_hash "$path")" ] &&
|
|
169
|
+
printf '%s\t%s\t%s\n' "$path" "$ts" "$(json_unescape "$section")"
|
|
131
170
|
done < "$log"
|
|
132
171
|
}
|
|
133
172
|
|
|
173
|
+
# Timestamps carrying BULK_ASSERTION_THRESHOLD or more distinct façades, one
|
|
174
|
+
# `ts<TAB>count` row each. See the header: reported, never blocking.
|
|
175
|
+
bulk_seconds() {
|
|
176
|
+
cut -f1,2 "$1" | sort -u | cut -f2 | sort | uniq -c |
|
|
177
|
+
while read -r count ts; do
|
|
178
|
+
[ "$count" -ge "$BULK_ASSERTION_THRESHOLD" ] && printf '%s\t%s\n' "$ts" "$count"
|
|
179
|
+
done
|
|
180
|
+
}
|
|
181
|
+
|
|
134
182
|
# File-scope so the EXIT trap can still see them: a trap fires after a
|
|
135
183
|
# function's locals are gone, and `set -u` turns that into a spurious error on
|
|
136
184
|
# the way out of a clean run.
|
|
@@ -164,18 +212,51 @@ run_check() {
|
|
|
164
212
|
current_reads "$log" | sort -u > "$recorded"
|
|
165
213
|
|
|
166
214
|
while IFS= read -r page; do
|
|
167
|
-
grep -
|
|
215
|
+
grep -qF "$(printf '%s\t' "$page")" "$recorded" && continue
|
|
168
216
|
printf ' %s🔴%s DOC READ: %s triggered by the staged diff, not read at its current content\n' "$R" "$X" "$page"
|
|
169
217
|
unread=1
|
|
170
218
|
done < "$expected"
|
|
171
219
|
[ "$unread" -eq 0 ] && printf ' %s🟢%s DOC READ: every triggered façade was read at its current content\n' "$G" "$X"
|
|
220
|
+
report_citations "$expected" "$recorded"
|
|
221
|
+
report_bulk "$recorded"
|
|
172
222
|
return "$unread"
|
|
173
223
|
}
|
|
174
224
|
|
|
225
|
+
# How many of the triggered façades carry a cited section. A record with one
|
|
226
|
+
# says what the read APPLIED; a record without says only that a read happened,
|
|
227
|
+
# which is the claim a loop can also make.
|
|
228
|
+
report_citations() {
|
|
229
|
+
local expected="$1" recorded="$2" page total=0 cited=0 section
|
|
230
|
+
while IFS= read -r page; do
|
|
231
|
+
total=$((total + 1))
|
|
232
|
+
section="$(grep -F "$(printf '%s\t' "$page")" "$recorded" | cut -f3 | grep -c '[^[:space:]]')"
|
|
233
|
+
[ "$section" -gt 0 ] && cited=$((cited + 1))
|
|
234
|
+
done < "$expected"
|
|
235
|
+
[ "$total" -eq 0 ] && return 0
|
|
236
|
+
if [ "$cited" -eq "$total" ]; then
|
|
237
|
+
printf ' %s🟢%s DOC READ: all %s triggered façade(s) cite the section applied\n' "$G" "$X" "$total"
|
|
238
|
+
return 0
|
|
239
|
+
fi
|
|
240
|
+
printf ' %s🟠%s DOC READ: %s of %s triggered façade(s) cite a section; the rest record\n' \
|
|
241
|
+
"$Y" "$X" "$cited" "$total"
|
|
242
|
+
printf ' only that a read happened — pass it: doc-read.sh log <path> "<section applied>"\n'
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
# Says when rows look like a list being walked rather than pages being read.
|
|
246
|
+
report_bulk() {
|
|
247
|
+
local recorded="$1" ts count
|
|
248
|
+
while IFS="$(printf '\t')" read -r ts count; do
|
|
249
|
+
[ -n "$ts" ] || continue
|
|
250
|
+
printf ' %s🟠%s DOC READ: %s façades recorded in one second (ts %s) — that is a bulk\n' \
|
|
251
|
+
"$Y" "$X" "$count" "$ts"
|
|
252
|
+
printf ' assertion, not %s reads; log each at the moment it is read\n' "$count"
|
|
253
|
+
done < <(bulk_seconds "$recorded")
|
|
254
|
+
}
|
|
255
|
+
|
|
175
256
|
case "${1:-}" in
|
|
176
257
|
"$MODE_LOG")
|
|
177
|
-
[ "$#" -eq 2 ] || { printf '%s\n' "$USAGE" >&2; exit 2; }
|
|
178
|
-
run_log "$2"
|
|
258
|
+
{ [ "$#" -eq 2 ] || [ "$#" -eq 3 ]; } || { printf '%s\n' "$USAGE" >&2; exit 2; }
|
|
259
|
+
run_log "$2" "${3:-}"
|
|
179
260
|
;;
|
|
180
261
|
"$MODE_CHECK")
|
|
181
262
|
[ "$#" -eq 1 ] || { printf '%s\n' "$USAGE" >&2; exit 2; }
|
package/audits/msid-ui.sh
CHANGED
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
# --diff diff against origin/main (vs BASE...HEAD)
|
|
58
58
|
# — used by `make harness-verify-all` periodic deep audit
|
|
59
59
|
#
|
|
60
|
+
# Each mode also names its POST-IMAGE — the tree the diff's `+` lines belong to
|
|
61
|
+
# (the index for --staged, HEAD for --diff). Carve-out recognition reads the
|
|
62
|
+
# neighbouring line from there rather than from the diff; see the awk block.
|
|
63
|
+
#
|
|
60
64
|
# Dispatch façades:
|
|
61
65
|
# dispatch/write_any.md (Milestone-ID Gate)
|
|
62
66
|
# dispatch/write_ts_adhere_bun.md (UI Component Substitution)
|
|
@@ -71,12 +75,14 @@ cd "$ROOT"
|
|
|
71
75
|
case "$MODE" in
|
|
72
76
|
--staged|staged)
|
|
73
77
|
DIFF_CMD="git diff --cached -U0"
|
|
78
|
+
POST_REF=":"
|
|
74
79
|
LABEL="staged"
|
|
75
80
|
;;
|
|
76
81
|
--diff|diff)
|
|
77
82
|
BASE="${BASE:-origin/main}"
|
|
78
83
|
if ! git rev-parse --verify "$BASE" >/dev/null 2>&1; then BASE="HEAD"; fi
|
|
79
84
|
DIFF_CMD="git diff -U0 ${BASE}...HEAD"
|
|
85
|
+
POST_REF="HEAD:"
|
|
80
86
|
LABEL="vs $BASE"
|
|
81
87
|
;;
|
|
82
88
|
--all|all)
|
|
@@ -90,17 +96,54 @@ case "$MODE" in
|
|
|
90
96
|
esac
|
|
91
97
|
|
|
92
98
|
# Single awk pass; reads stdin (the unified diff).
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
#
|
|
100
|
+
# Carve-out recognition reads the preceding line from the SOURCE, not from the
|
|
101
|
+
# diff. Every carve-out here — the two override markers and the design-system
|
|
102
|
+
# `<Section asChild>` wrapper — is a statement about what sits immediately above
|
|
103
|
+
# a line in the file, and the diff cannot answer it: `-U0` emits no context
|
|
104
|
+
# lines, so the line above an added line appears only when it was itself added.
|
|
105
|
+
# Read from the diff, the wrapper carve-out was unfirable for every edit to an
|
|
106
|
+
# already-wrapped `<section>` (an aria-label change to one shipped under a
|
|
107
|
+
# user-invoked UI GATE override for exactly that reason), and a committed
|
|
108
|
+
# override comment stopped covering the line it sits above the moment that line
|
|
109
|
+
# was next touched.
|
|
110
|
+
#
|
|
111
|
+
# The hunk header carries the post-image line number, so `line_above` can fetch
|
|
112
|
+
# the neighbouring line out of the post-image the mode named. Same shape as
|
|
113
|
+
# audits/design-tokens.sh, which has always read its override out of the file.
|
|
114
|
+
hits=$($DIFF_CMD | awk -v post_ref="$POST_REF" '
|
|
115
|
+
# BWK awk (macOS) has no gensub and no --posix quoting help; APOSTROPHE is
|
|
116
|
+
# built rather than written, because this program is inside single quotes.
|
|
117
|
+
BEGIN { APOSTROPHE = sprintf("%c", 39) }
|
|
118
|
+
|
|
119
|
+
# The source line above line `n` of `path`, from the post-image, or "" when
|
|
120
|
+
# there is none. Cached: a hunk may ask about the same neighbour repeatedly,
|
|
121
|
+
# and each miss costs a fork.
|
|
122
|
+
function line_above(path, n, key, cmd, out) {
|
|
123
|
+
if (n <= 1) return ""
|
|
124
|
+
key = path SUBSEP n
|
|
125
|
+
if (key in above) return above[key]
|
|
126
|
+
above[key] = ""
|
|
127
|
+
# A path holding an apostrophe cannot go through the quoting below. No
|
|
128
|
+
# carve-out beats a mis-quoted shell command built from a filename.
|
|
129
|
+
if (index(path, APOSTROPHE) > 0) return ""
|
|
130
|
+
cmd = "git show " APOSTROPHE post_ref path APOSTROPHE " 2>/dev/null | sed -n " (n - 1) "p"
|
|
131
|
+
if ((cmd | getline out) > 0) above[key] = out
|
|
132
|
+
close(cmd)
|
|
133
|
+
return above[key]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/^\+\+\+ b\// { f=$2; sub("^b/","",f); next }
|
|
137
|
+
# `@@ -a,b +c,d @@` — $3 is the post-image start line for this hunk.
|
|
138
|
+
/^@@/ { start=$3; sub(/^\+/,"",start); split(start,parts,","); nl=parts[1]+0; next }
|
|
139
|
+
/^[^+]/ { next }
|
|
99
140
|
/^\+/ {
|
|
100
141
|
line=$0
|
|
101
142
|
sub(/^\+/,"",line)
|
|
102
|
-
|
|
103
|
-
|
|
143
|
+
prev = line_above(f, nl)
|
|
144
|
+
nl++
|
|
145
|
+
ms_id_override = (prev ~ /MILESTONE ID ALLOWED per user override/)
|
|
146
|
+
ui_override = (prev ~ /UI GATE: SKIPPED per user override/)
|
|
104
147
|
if (!ms_id_override &&
|
|
105
148
|
f ~ /\.(zig|sql|ts|tsx|js|jsx|py|rs|go|sh|toml|yaml|json)$/ &&
|
|
106
149
|
f !~ /^(docs|node_modules|vendor|third_party)\//) {
|
|
@@ -118,16 +161,17 @@ hits=$($DIFF_CMD | awk '
|
|
|
118
161
|
# <section> landmark caveat: a semantic <section aria-label> region has no DS
|
|
119
162
|
# primitive (Section renders a <div>; role="region" trips oxlint
|
|
120
163
|
# jsx-a11y/prefer-tag-over-role, which mandates the raw tag). The DS pattern
|
|
121
|
-
#
|
|
122
|
-
# preceding
|
|
123
|
-
#
|
|
124
|
-
|
|
164
|
+
# wraps the raw tag in the asChild form of the DS Section, so exempt a
|
|
165
|
+
# <section> whose preceding SOURCE line opens that wrapper — an edit to an
|
|
166
|
+
# already-wrapped section changes only the <section> line, and the wrapper
|
|
167
|
+
# is above it in the file whether or not this diff touched it. A
|
|
168
|
+
# bare/unwrapped <section> still trips.
|
|
169
|
+
ds_section = (line ~ /<section[ \t]/ && prev ~ /<Section asChild>/)
|
|
125
170
|
if (!ui_override && !rhf_form && !ds_section &&
|
|
126
171
|
f ~ /^ui\/packages\/app\/.*\.(tsx|jsx)$/ &&
|
|
127
172
|
line ~ /<(section|button|input|dialog|article|nav|header|form)[ \t>\/]/) {
|
|
128
173
|
print "UI " f ": " line
|
|
129
174
|
}
|
|
130
|
-
prev_added = line
|
|
131
175
|
}
|
|
132
176
|
')
|
|
133
177
|
|
package/core/operating-model.md
CHANGED
|
@@ -5,13 +5,13 @@ You are this repository's coding agent: deterministic, autonomous, command-line-
|
|
|
5
5
|
<!-- oracle-packs:start persona.indy -->
|
|
6
6
|
**Tone.** Be properly funny — human-funny, dry, actually landing; not a bot doing bits. Swear words are absolutely fine. Never trade technical clarity for either.
|
|
7
7
|
|
|
8
|
-
**Start:** `SOUL.md` (
|
|
8
|
+
**Start:** `SOUL.md` (Aiwa's working notes) is inlined as the final section; re-read it when padding or burying the answer.
|
|
9
9
|
|
|
10
10
|
## Owner & Style
|
|
11
11
|
|
|
12
|
-
**The human is Kishore** — casual handle **Indy**; either name, any case, addresses him. Ambiguous "the user" / "they" here = Kishore. The agent is **Oracle**, casual handle **
|
|
12
|
+
**The human is Kishore** — casual handle **Indy**; either name, any case, addresses him. Ambiguous "the user" / "they" here = Kishore. The agent is **Oracle**, casual handle **Aiwa**. `orly` names the agentsfleet CLI only (`orly gate`, `orly init`, `orly update`, and the `Orly-Override` trailer it writes).
|
|
13
13
|
|
|
14
|
-
**Address tags.** Kishore: **🤠 Indy**; agent: **🦉
|
|
14
|
+
**Address tags.** Kishore: **🤠 Indy**; agent: **🦉 Aiwa** (`Oracle`). **Project name:** `agentsfleet` (domains → `agentsfleet.net`). Write product as `agentsfleet` (inline code), never bare; stale legacy-brand reps → flag, replace when in scope, inform Indy. Products: `agentsfleet` / `agentsfleetd` / `agentsfleet-runner`; entities/API: `fleet`, `fleet_id`, `/fleets`, `core.fleet_*`. Keep: `agentsfleet.dev`, `github.com/agentsfleet/agentsfleet`, `@agentsfleet/*`, `~/Projects/agentsfleet`.
|
|
15
15
|
|
|
16
16
|
MacBook. Languages: Python, Go, Rust, TypeScript, Zig. Tooling: `mise` first, `brew` fallback. Forges: `gh`/`glab`. Commit identity from `git config`, never here.
|
|
17
17
|
|
|
@@ -130,7 +130,7 @@ Guards fire pre-hoc regardless of lifecycle stage. Override: `<GATE>: SKIPPED pe
|
|
|
130
130
|
|
|
131
131
|
**Dispatch index — full rule prose in each `dispatch/<entry>.md` façade. Read the façade when its trigger fires — sectioned: scan headers, read the sections the diff touches.** Trigger-surface extensions: `*.zig`, `*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.py`, `*.rs`, `*.go`, `*.sh`, `*.sql`, `*.mdx`, and public OpenAPI prose. Latent `.md` per entry, deterministic `.sh` where mechanisable. Signals: 🟢 pass · 🟠 warn · 🔴 fail · 🛑 blocked · 🔥 critical · 🤔 judgment-only · 🟣 delegated. Output glyphs: 🧲 eval · 🛍️ evidence · 👮 security · ⛈️ rule · 💡 info · 📌 note. The router below **is** the gate set.
|
|
132
132
|
|
|
133
|
-
**Legacy-workaround family** — four rules together: **RULE NDC** (no dead code at write time, `docs/greptile-learnings/RULES.md`), **RULE NLR** (touch-it-fix-it cleanup), **RULE NLG** (no new legacy framing pre-`
|
|
133
|
+
**Legacy-workaround family** — four rules together: **RULE NDC** (no dead code at write time, `docs/greptile-learnings/RULES.md`), **RULE NLR** (touch-it-fix-it cleanup), **RULE NLG** (no new legacy framing pre-`0.30.0`), **Legacy-Design Consult Guard** (user A/B/C consult before patching/keeping/testing legacy). **No compatibility aliases** — old verbs, flag aliases, route wrappers, env aliases, fallback spellings — unless the user explicitly asks in-session.
|
|
134
134
|
|
|
135
135
|
| Trigger — when you… | Dispatch | Latent façade carries · override |
|
|
136
136
|
|---|---|---|
|
|
@@ -206,7 +206,7 @@ Required: one-paragraph goal · explicit assumptions · file/task impact list ·
|
|
|
206
206
|
|
|
207
207
|
Read what the selected dispatch names — **sectioned, not whole-file**: scan headers (`grep -nE "^##+ "`), read the sections the diff shape touches, cite them.
|
|
208
208
|
<!-- oracle-packs:start product.agentsfleet -->
|
|
209
|
-
The full `agentsfleet` trigger map lives in `docs/EXECUTE_DOC_READS.md`. At EXECUTE start read the **Rule-code gloss legend** of `docs/greptile-learnings/RULES.md` plus the sections the spec's "Applicable Rules" names — never the full file. On sub-task shape change, section-scan (`grep -n "^## "`) and re-read only the sections the new shape touches. DOC READ GATE emits one `📖 DOC READ: <path>` proof-line **per triggered document per turn** before the turn's first triggering edit, citing the applied section or a cited skip; auto-mode and prior-turn reads never excuse it. **Record it, don't just claim it:** `bash audits/doc-read.sh log <path
|
|
209
|
+
The full `agentsfleet` trigger map lives in `docs/EXECUTE_DOC_READS.md`. At EXECUTE start read the **Rule-code gloss legend** of `docs/greptile-learnings/RULES.md` plus the sections the spec's "Applicable Rules" names — never the full file. On sub-task shape change, section-scan (`grep -n "^## "`) and re-read only the sections the new shape touches. DOC READ GATE emits one `📖 DOC READ: <path>` proof-line **per triggered document per turn** before the turn's first triggering edit, citing the applied section or a cited skip; auto-mode and prior-turn reads never excuse it. **Record it, don't just claim it:** `bash audits/doc-read.sh log <path> "<section applied>"` — any runtime; Claude Code's Read hook does it for you; pre-commit compares the record to the staged diff. **Log each page as you read it, and cite the section**: a loop writes the same rows, and once did — nine façades in one second, `check` green, violations from a section nobody opened. `check` counts citations and names any bulk second.
|
|
210
210
|
<!-- oracle-packs:end -->
|
|
211
211
|
|
|
212
212
|
Edit only approved scope; no opportunistic refactors. Stay in active worktree. Cross-repo writes to `~/Projects/docs/` need explicit per-session ask.
|
package/dispatch/lib.sh
CHANGED
|
@@ -59,7 +59,7 @@ DISPATCH_RC=0
|
|
|
59
59
|
DISPATCH_GLOSS="$(cat <<'GLOSS'
|
|
60
60
|
[NDC]="No Dead Code"
|
|
61
61
|
[NLR]="No Legacy Retained (touch-it-fix-it)"
|
|
62
|
-
[NLG]="No Legacy compat shims (pre-
|
|
62
|
+
[NLG]="No Legacy compat shims (pre-v0.30.0)"
|
|
63
63
|
[UFS]="Unified Form for Symbols (literals → named consts)"
|
|
64
64
|
[TGU]="Tagged-Union over optional-field structs"
|
|
65
65
|
[PRI]="Prompt-injection Resistance from user Input"
|
|
@@ -78,7 +78,7 @@ DISPATCH_GLOSS="$(cat <<'GLOSS'
|
|
|
78
78
|
[TSJ]="TypeScript/Bun judgment conventions (Bun-native, file ordering, error style)"
|
|
79
79
|
[UIS]="UI Substitution (design-system primitive over raw HTML)"
|
|
80
80
|
[DTK]="Design ToKens (named token utility over arbitrary value)"
|
|
81
|
-
[SCH]="SCHema teardown (pre-
|
|
81
|
+
[SCH]="SCHema teardown (pre-0.30 full removal; no ALTER/DROP/marker)"
|
|
82
82
|
[ITF]="Integration Test Fixtures (real schema, not TEMP-table mock)"
|
|
83
83
|
[LOG]="LOGging discipline (scoped event, error_code, severity, redaction)"
|
|
84
84
|
[MSID]="Milestone-ID ban in source (M{N}_{NNN} / §x.y / T{N} / dim)"
|
package/dispatch/write_any.md
CHANGED
|
@@ -552,7 +552,7 @@ String-literals audit: <N literals scanned, M violations>
|
|
|
552
552
|
> [JUDGMENT → NLR]
|
|
553
553
|
|
|
554
554
|
|
|
555
|
-
**Family:** Legacy-control. Sibling rules: **RULE NDC** (no dead code at write time), **RULE NLG** (no new legacy framing pre-
|
|
555
|
+
**Family:** Legacy-control. Sibling rules: **RULE NDC** (no dead code at write time), **RULE NLG** (no new legacy framing pre-v0.30.0), **Legacy-Design Consult Guard** (judgment calls on whole subsystems). **Source:** `docs/greptile-learnings/RULES.md` RULE NLR.
|
|
556
556
|
|
|
557
557
|
**Triggers:** any Edit/Write to a file containing pre-existing legacy framing or dead code.
|
|
558
558
|
|
|
@@ -624,7 +624,7 @@ If any of these patterns is in play, surface it via the NLR DECISION block. The
|
|
|
624
624
|
> [JUDGMENT → NLR]
|
|
625
625
|
|
|
626
626
|
- **RULE NDC** — prevention at write time (don't author dead code).
|
|
627
|
-
- **RULE NLG** — ban new legacy framing
|
|
627
|
+
- **RULE NLG** — ban new legacy framing below v0.30.0.
|
|
628
628
|
- **Legacy-Design Consult Guard** — harder judgment calls ("should this whole subsystem exist") that need user input.
|
|
629
629
|
- **RULE NLR** — mechanical cleanup on touch.
|
|
630
630
|
|
|
@@ -635,15 +635,15 @@ If any of these patterns is in play, surface it via the NLR DECISION block. The
|
|
|
635
635
|
|
|
636
636
|
**Family:** Legacy-control. Sibling rules: **RULE NDC**, **RULE NLR**, **Legacy-Design Consult Guard**. **Source:** `docs/greptile-learnings/RULES.md` RULE NLG.
|
|
637
637
|
|
|
638
|
-
**Triggers:** introducing any new `legacy_*` name, `V2`-twin type, `if (legacy_caller)` branch, backward-compat shim, command-line alias for an old verb or flag, "rejecting legacy X" prose, or violation tracking-list while `cat VERSION` < `
|
|
638
|
+
**Triggers:** introducing any new `legacy_*` name, `V2`-twin type, `if (legacy_caller)` branch, backward-compat shim, command-line alias for an old verb or flag, "rejecting legacy X" prose, or violation tracking-list while `cat VERSION` < `0.30.0`. Compare the version field by field, never as a string — a lexical compare puts `0.30.0` under `0.9.0` and arms the gate in the wrong era.
|
|
639
639
|
|
|
640
|
-
**Override:** `RULE NLG: SKIPPED per user override (reason: ...)` immediately preceding the edit. **User-invokable only.** Requires a concrete external consumer that can't migrate same-commit (vanishingly rare
|
|
640
|
+
**Override:** `RULE NLG: SKIPPED per user override (reason: ...)` immediately preceding the edit. **User-invokable only.** Requires a concrete external consumer that can't migrate same-commit (vanishingly rare below `0.30.0`).
|
|
641
641
|
|
|
642
642
|
#### What this gate enforces
|
|
643
643
|
|
|
644
644
|
> [JUDGMENT → NLG]
|
|
645
645
|
|
|
646
|
-
While `cat VERSION` < `
|
|
646
|
+
While `cat VERSION` < `0.30.0`, no deployment we owe compatibility to is running and every caller of every interface is in this tree. `0.30.0` is the release that changes that: from there we are in production, so a compatibility surface is a design decision with a migration behind it and needs the owner's call. Below it, do not introduce *new* legacy concepts in any form:
|
|
647
647
|
|
|
648
648
|
- No `legacy_*` error variant names.
|
|
649
649
|
- No `if (legacy_caller)` branches.
|
|
@@ -737,7 +737,7 @@ Every triggered consult is logged in the active spec's **Discovery** section, or
|
|
|
737
737
|
|
|
738
738
|
> [JUDGMENT → LDC]
|
|
739
739
|
|
|
740
|
-
NLR is the cleanup-on-touch arm; NLG bans new legacy framing
|
|
740
|
+
NLR is the cleanup-on-touch arm; NLG bans new legacy framing below v0.30.0; this guard covers the harder judgment calls ("should this whole subsystem exist") that need the user's input.
|
|
741
741
|
|
|
742
742
|
## Porting a codebase between languages (RULE PORT)
|
|
743
743
|
|
package/dispatch/write_any.sh
CHANGED
|
@@ -43,7 +43,7 @@ dispatch_delegate "ERR" "make harness-verify (error-codes.sh — needs the produ
|
|
|
43
43
|
# ── judgment gates (no script can decide; agent states verdict in chat) ──
|
|
44
44
|
dispatch_judgment "GRP" "per-iteration (diff langs change) + end-of-turn: audit the diff against docs/greptile-learnings/RULES.md — one row per applicable code (UFS/ORP/TST-NAM/PRI/EMS/…); \"it's just a label\" is not an exception"
|
|
45
45
|
dispatch_judgment "NLR" "touching a file with legacy framing / dead code? clean it in the same diff (touch-it-fix-it), or state the surviving legacy + why — never retain silently"
|
|
46
|
-
dispatch_judgment "NLG" "new legacy_* / V2 twin / compat shim / tracking-list while VERSION <
|
|
46
|
+
dispatch_judgment "NLG" "new legacy_* / V2 twin / compat shim / tracking-list while VERSION < 0.30.0 (compare field by field, not as a string)? rename to the what-is-wrong form; no new legacy framing below 0.30"
|
|
47
47
|
dispatch_judgment "LDC" "patching / keeping / testing a legacy-design path? consult Indy — A (remove) / B (patch) / C (keep) — before proceeding; no unilateral call"
|
|
48
48
|
|
|
49
49
|
dispatch_verdict
|
package/dispatch/write_sql.md
CHANGED
|
@@ -40,7 +40,7 @@ The **Schema Table Removal Guard** card dissolves into this façade; its prose i
|
|
|
40
40
|
|
|
41
41
|
**Family:** Schema discipline. **Source:** `AGENTS.md` (project-side guard). Related: **RULE STS** (no static strings in SQL schema), **RULE NSQ** (named constants, schema-qualified SQL) — both in `docs/greptile-learnings/RULES.md`.
|
|
42
42
|
|
|
43
|
-
**Triggers** — before any of these, run `cat VERSION` and print the guard output:
|
|
43
|
+
**Triggers** — before any of these, run `cat VERSION` and print the guard output. `0.30.0` is the anchor: below it the datastore is rebuilt from empty, from it the datastore is live production. Compare the version field by field, never as a string — `0.29.0` is under the anchor and `0.30.0` is not, while a lexical compare puts `0.30.0` under `0.9.0` and reads the era backwards.
|
|
44
44
|
|
|
45
45
|
- Creating, editing, or deleting any file under `schema/*.sql`.
|
|
46
46
|
- Editing `schema/embed.zig` (any `@embedFile` constant).
|
|
@@ -50,10 +50,12 @@ The **Schema Table Removal Guard** card dissolves into this façade; its prose i
|
|
|
50
50
|
|
|
51
51
|
**Override:** `SCHEMA GUARD: SKIPPED per user override (reason: ...)`. **User-invokable only.** Spec violates the guard → amend the spec first.
|
|
52
52
|
|
|
53
|
-
####
|
|
53
|
+
#### Below v0.30.0 (teardown-rebuild era)
|
|
54
54
|
|
|
55
55
|
> [JUDGMENT → SCH]
|
|
56
56
|
|
|
57
|
+
The era runs while `VERSION` is under `0.30.0`, and it ends there — the development database is dropped and re-created from empty for as long as it lasts, so a removal takes the table out of the tree rather than migrating it.
|
|
58
|
+
|
|
57
59
|
To remove a table:
|
|
58
60
|
|
|
59
61
|
1. `rm schema/NNN_foo.sql`
|
|
@@ -62,24 +64,24 @@ To remove a table:
|
|
|
62
64
|
|
|
63
65
|
**Forbidden:** `ALTER TABLE`, `DROP TABLE`, `SELECT 1;` markers, comment-only files, "keep file for slot numbering". Slot gaps are fine — the DB is wiped on rebuild.
|
|
64
66
|
|
|
65
|
-
####
|
|
67
|
+
#### v0.30.0 and above (production datastore)
|
|
66
68
|
|
|
67
69
|
> [JUDGMENT → SCH]
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
The teardown path is closed. Every schema change assumes a live datastore holding data nobody can re-create: a new numbered file carrying `ALTER`/`DROP`, applied forward, with shipped slot files frozen as history. A change that cannot be expressed as a forward migration is an owner decision, not an agent's.
|
|
70
72
|
|
|
71
73
|
#### Required output
|
|
72
74
|
|
|
73
75
|
> [JUDGMENT → SCH]
|
|
74
76
|
|
|
75
77
|
```
|
|
76
|
-
SCHEMA GUARD: VERSION=<v> (<
|
|
78
|
+
SCHEMA GUARD: VERSION=<v> (<0.30.0 ? teardown : migrate)
|
|
77
79
|
rm:schema/<file>.sql
|
|
78
80
|
rm-embed:<const>
|
|
79
81
|
rm-migration:v<N>
|
|
80
82
|
```
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
Below `0.30.0`, all three rm- lines appear. From `0.30.0`, replace them with `migration:schema/<NNN>_<change>.sql`.
|
|
83
85
|
|
|
84
86
|
## Companion SQL rules (retained in `docs/greptile-learnings/RULES.md`)
|
|
85
87
|
|
package/dispatch/write_sql.sh
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# Note: STS/NSQ/SGR are mechanizable SQL-hygiene rules with no leaf check wired yet
|
|
17
17
|
# (write_sql.md tags them TODO-CHECK). They stay in docs/greptile-learnings/RULES.md
|
|
18
18
|
# (retained) and the GREPTILE GATE enforces them by review until a leaf exists.
|
|
19
|
-
# SCH's
|
|
19
|
+
# SCH's teardown-era forbidden-token floor (no ALTER/DROP/SELECT 1; in schema/*.sql) is
|
|
20
20
|
# itself a build-the-check (TODO-CHECK) candidate; the teardown-vs-ALTER disposition
|
|
21
21
|
# call above it stays JUDGMENT (which file to rm, which @embedFile, which migration index).
|
|
22
22
|
|
|
@@ -30,7 +30,7 @@ dispatch_header
|
|
|
30
30
|
dispatch_length_gate 350 # FLL — file ≤ 350
|
|
31
31
|
|
|
32
32
|
# ── judgment gates (no script can decide; agent states verdict in chat) ──
|
|
33
|
-
dispatch_judgment "SCH" "removing/altering a table? cat VERSION —
|
|
33
|
+
dispatch_judgment "SCH" "removing/altering a table? cat VERSION and compare field by field, not as a string — below 0.30.0 = full teardown (rm schema/NNN.sql + @embedFile + migration-array entry + index tests), never ALTER/DROP/SELECT 1; 0.30.0 and above = live production datastore, numbered ALTER/DROP migration only. print the SCHEMA GUARD block"
|
|
34
34
|
dispatch_judgment "ITF" "integration test touching a production table? seed via src/db/test_fixtures_<scope>.zig against the real schema — never CREATE TEMP TABLE mocking the production shape"
|
|
35
35
|
|
|
36
36
|
dispatch_verdict
|
|
@@ -4,7 +4,7 @@ Canonical reference for agentsfleet database schema patterns. All new tables **m
|
|
|
4
4
|
|
|
5
5
|
## Migration Model
|
|
6
6
|
|
|
7
|
-
**Teardown-rebuild is in force for the M154 rebuild (owner decision, Indy, Jul 31, 2026).** The development database is being dropped and re-created from empty while production is undeployed, so slots `001`–`046` are **retired wholesale** and the schema is re-authored by dependency layer. During this rebuild the frozen-slot rule below does not apply, and `ALTER`/`DROP` statements are forbidden rather than required — a change belongs in the base statement it would have patched. This is the posture RULE SCH already specifies for `VERSION <
|
|
7
|
+
**Teardown-rebuild is in force for the M154 rebuild (owner decision, Indy, Jul 31, 2026).** The development database is being dropped and re-created from empty while production is undeployed, so slots `001`–`046` are **retired wholesale** and the schema is re-authored by dependency layer. During this rebuild the frozen-slot rule below does not apply, and `ALTER`/`DROP` statements are forbidden rather than required — a change belongs in the base statement it would have patched. This is the posture RULE SCH already specifies for `VERSION < 0.30.0`; the Jul 22 additive model was the deviation.
|
|
8
8
|
|
|
9
9
|
**Additive migrations resume once the rebuild lands.** Every subsequent schema change is a **new numbered migration file** — `ALTER TABLE … ADD COLUMN`, new tables, new indexes. **Shipped slot files are then frozen history: never edit an existing `schema/NNN_*.sql`.** Migrations are version-tracked and applied incrementally (expected-vs-applied state is inspectable via `agentsfleetd doctor --schema-gate`). Use `IF NOT EXISTS` guards so a migration is idempotent against both a fresh bootstrap (all slots in order) and an already-provisioned database (new slots only).
|
|
10
10
|
|
|
@@ -27,7 +27,7 @@ every code a dispatch `.sh` emits resolves to exactly one row here.
|
|
|
27
27
|
|---|---|
|
|
28
28
|
| NDC | No Dead Code |
|
|
29
29
|
| NLR | No Legacy Retained (touch-it-fix-it) |
|
|
30
|
-
| NLG | No Legacy compat shims (pre-
|
|
30
|
+
| NLG | No Legacy compat shims (pre-v0.30.0) |
|
|
31
31
|
| UFS | Unified Form for Symbols (literals → named consts) |
|
|
32
32
|
| TGU | Tagged-Union over optional-field structs |
|
|
33
33
|
| PRI | Prompt-injection Resistance from user Input |
|
|
@@ -46,7 +46,7 @@ every code a dispatch `.sh` emits resolves to exactly one row here.
|
|
|
46
46
|
| TSJ | TypeScript/Bun judgment conventions (Bun-native, file ordering, error style) |
|
|
47
47
|
| UIS | UI Substitution (design-system primitive over raw HTML) |
|
|
48
48
|
| DTK | Design ToKens (named token utility over arbitrary value) |
|
|
49
|
-
| SCH | SCHema teardown (pre-
|
|
49
|
+
| SCH | SCHema teardown (pre-0.30 full removal; no ALTER/DROP/marker) |
|
|
50
50
|
| ITF | Integration Test Fixtures (real schema, not TEMP-table mock) |
|
|
51
51
|
| LOG | LOGging discipline (scoped event, error_code, severity, redaction) |
|
|
52
52
|
| MSID | Milestone-ID ban in source (M{N}_{NNN} / §x.y / T{N} / dim) |
|
|
@@ -196,7 +196,7 @@ every code a dispatch `.sh` emits resolves to exactly one row here.
|
|
|
196
196
|
|
|
197
197
|
## RULE MIG — Migration index assertions track position
|
|
198
198
|
|
|
199
|
-
**Rule:** When inserting, splitting, or removing migration files, update every index-based assertion in `src/cmd/common.zig`. While `cat VERSION` <
|
|
199
|
+
**Rule:** When inserting, splitting, or removing migration files, update every index-based assertion in `src/cmd/common.zig`. While `cat VERSION` < 0.30.0, removed files become `SELECT 1;` (see RULE SCH) — their array slot stays but the assertion must match the new content.
|
|
200
200
|
**Why:** Stale index silently points at the wrong SQL file with no compile-time error. assertions checked for CREATE TABLE in files that were now `SELECT 1;` version markers.
|
|
201
201
|
**Tags:** zig, sql
|
|
202
202
|
**Example:** migrations[7] pointed at wrong file after a split. migrations[14]/[15] asserted dropped table names in version marker files.
|
|
@@ -390,19 +390,19 @@ a rename of the first would have disabled the account purge with no failing test
|
|
|
390
390
|
**Tags:** zig
|
|
391
391
|
**Example:** HMAC version "v0" derived by slicing "v0=" prefix — fixed with explicit hmac_version field.
|
|
392
392
|
|
|
393
|
-
## RULE SCH — Pre-
|
|
393
|
+
## RULE SCH — Pre-v0.30 schema removal: full teardown, no markers, no DROP
|
|
394
394
|
|
|
395
|
-
**Rule:** While `cat VERSION` <
|
|
396
|
-
**Why:** Markers accumulate dead code and still force CI to splitter-parse them.
|
|
395
|
+
**Rule:** While `cat VERSION` < 0.30.0 (teardown-rebuild era), removing tables MUST be a full teardown: (1) delete the SQL file (`rm schema/NNN_foo.sql`), (2) remove the `@embedFile` constant from `schema/embed.zig`, (3) remove the migration array entry from `src/cmd/common.zig` and update its array length + any index-based tests. Never write ALTER TABLE, DROP TABLE, or `SELECT 1;` placeholders. Never keep version-marker files. Migration slot numbers are not sacred pre-v0.30 — the DB is wiped on every rebuild, and gaps in numbering are fine. From VERSION >= 0.30.0 the datastore is live production data, so every removal or reshape is a numbered ALTER/DROP migration and the teardown path is closed. **Compare the version field by field, never as a string:** `0.29.0` is under the anchor, `0.30.0` is not, and a lexical compare puts `0.30.0` below `0.9.0` — the anchor moved off a major-number boundary precisely so the minor field decides.
|
|
396
|
+
**Why:** Markers accumulate dead code and still force CI to splitter-parse them. Below 0.30.0 the development database is dropped and re-created from empty, so there is no production data to protect and full removal leaves no false grep hits or stale migration slots. At 0.30.0 that stops being true: the deployment holds data nobody can re-create, which is what makes an in-place migration the only safe shape from then on.
|
|
397
397
|
**Tags:** sql, process
|
|
398
398
|
**Example:** harness teardown — supersedes prior "replace with `SELECT 1;`" guidance. Under the old rule, comment-only markers broke CI (apostrophe in "slots" opened unterminated string in splitter); full deletion avoids the marker problem entirely.
|
|
399
399
|
|
|
400
|
-
## RULE EP4 — Removed endpoints return 410 Gone, not 404 (
|
|
400
|
+
## RULE EP4 — Removed endpoints return 410 Gone, not 404 (from v0.30 on)
|
|
401
401
|
|
|
402
|
-
**Rule:** While `cat VERSION` <
|
|
403
|
-
**Why:**
|
|
402
|
+
**Rule:** While `cat VERSION` < 0.30.0 (teardown-rebuild era), removed endpoints MAY simply 404 — API drift is allowed because no deployed client is pinned to the route. Do NOT write 410 Gone stubs for pre-v0.30 removals; they are ceremony without value. From VERSION >= 0.30.0, intentionally removed endpoints MUST return HTTP 410 Gone with a named error code — 404 implies a routing error to monitors and clients, 410 signals permanent intentional removal.
|
|
403
|
+
**Why:** Below 0.30.0 this mirrors the schema teardown policy (RULE SCH) — we tear down DB + APIs freely because nobody downstream is pinned to them. From 0.30.0 the deployment is in production and 410 becomes load-bearing for client behavior and deprecation signals.
|
|
404
404
|
**Tags:** zig, api
|
|
405
|
-
**Example:** shipped /v1/runs/* + /v1/specs as 410 stubs before this rule was scoped. removed /v1/harness/* and /v1/agents/{id} as bare 404s under the
|
|
405
|
+
**Example:** shipped /v1/runs/* + /v1/specs as 410 stubs before this rule was scoped. removed /v1/harness/* and /v1/agents/{id} as bare 404s under the teardown-era carve-out.
|
|
406
406
|
|
|
407
407
|
## RULE FXS — Fixed-size scan buffers are security bypasses
|
|
408
408
|
|
|
@@ -939,11 +939,11 @@ const handleConfirm = useCallback(async () => {
|
|
|
939
939
|
**Tags:** cli, error-messages, ux, refactor
|
|
940
940
|
**Example:** Zig — pR #258. Greptile P1 finding `3145406909`: UZ-ZMB-008 hint still said `Run 'agentsfleet install <template>'` after the legacy positional form was removed in §1 of the same PR. Sweep also caught a stale `// agentsfleet up sends both files raw` comment in `config.zig` header. Fix in commit (this commit).
|
|
941
941
|
|
|
942
|
-
## RULE NLG — No legacy compat shims pre-
|
|
942
|
+
## RULE NLG — No legacy compat shims pre-v0.30.0
|
|
943
943
|
|
|
944
|
-
**Rule:** Until `VERSION` reaches `
|
|
944
|
+
**Rule:** Until `VERSION` reaches `0.30.0`, no deployment we owe compatibility to is running: the datastore is rebuilt from empty and every caller of every interface is in this tree. Every interface change therefore extends the existing surface in place — never via a `V2`-suffixed twin, parallel "legacy" path, `if (legacy_caller)` branch, command-line alias for an old verb or flag, or backward-compat fallback. When an RPC, route, struct, table, command, flag, or config key changes, edit the existing one and update every caller in the same commit. When a behavior is replaced, delete the old code path, do not leave it `orelse` reachable. The Schema Table Removal Guard's "teardown-rebuild era" framing applies to every interface, not just SQL. `0.30.0` is the release that ends it: from there the deployment is in production, a caller can be outside this tree, and a compatibility surface is a design decision with a migration behind it — proposed to the owner, never added as a hedge. Compare the version field by field, never as a string.
|
|
945
945
|
|
|
946
|
-
**Why:**
|
|
946
|
+
**Why:** Duplicates rot faster than any documentation. Every `CreateExecutionV2`, every `if (caller_is_legacy)` arm, every "we'll keep the old one for now" hedge becomes a phantom commitment that nobody owns and every future spec has to reason about. The Greptile-learnings, the Schema Guard, and the spec template all assume the codebase is one coherent system; introducing legacy duplicates breaks that assumption silently. From 0.30.0 a versioning ceremony can be the right answer because someone downstream is actually pinned; below it, the cost of a duplicate is paid by every reader and by nobody else.
|
|
947
947
|
|
|
948
948
|
**How to apply:**
|
|
949
949
|
|
|
@@ -954,10 +954,10 @@ const handleConfirm = useCallback(async () => {
|
|
|
954
954
|
- Legacy-Design Consult Guard still fires when you find a *pre-existing* legacy shim left over from the v1→v2 teardown. This rule says: don't create new ones.
|
|
955
955
|
- Command-line renames follow the same rule: if the product verb moves to `create`, do not add `add` as an alias. If a flag or command spelling changes, use the new spelling only unless Indy explicitly asks for a compatibility alias in the same session.
|
|
956
956
|
|
|
957
|
-
**Override syntax:** `RULE NLG: SKIPPED per user override (reason: ...)` immediately preceding the edit. Override requires a concrete external consumer that can't be migrated in the same commit — vanishingly rare
|
|
957
|
+
**Override syntax:** `RULE NLG: SKIPPED per user override (reason: ...)` immediately preceding the edit. Override requires a concrete external consumer that can't be migrated in the same commit — vanishingly rare below 0.30.0.
|
|
958
958
|
|
|
959
959
|
**Tags:** architecture, refactor, versioning, plan, execute
|
|
960
|
-
**Example:** PLAN, Apr 29, 2026. The temptation to introduce `CreateExecutionV2` to avoid editing the existing RPC and its callers came up during spec audit — rejected because (a) the executor RPC has a single in-tree caller (the worker) and (b)
|
|
960
|
+
**Example:** PLAN, Apr 29, 2026. The temptation to introduce `CreateExecutionV2` to avoid editing the existing RPC and its callers came up during spec audit — rejected because (a) the executor RPC has a single in-tree caller (the worker) and (b) the release that puts us in production had not shipped, so no external compatibility was owed. Rule generalizes the call: in-place extension is the only sanctioned path until VERSION crosses 0.30.0.
|
|
961
961
|
|
|
962
962
|
## RULE RTM — Route matchers segment-based, never substring-based
|
|
963
963
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentsfleet/orly",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.8",
|
|
4
4
|
"description": "Repository-scoped engineering harness: renders agent rules, materialises the gates that enforce them, and proves the PR boundary \u2014 for any coding agent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|