@agentsfleet/orly 0.10.6 → 0.10.7
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 +1 -1
- package/audits/doc-read.sh +97 -16
- package/core/operating-model.md +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -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
|
|
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/core/operating-model.md
CHANGED
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentsfleet/orly",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.7",
|
|
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",
|