Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion PORTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ consequence is a Cursor API reaching a generated skill while every other check s
fix is to correct the left-hand side against what upstream actually says now, or to record the rule
in `omp-port/stale-exempt.tsv` with a reason. That file is keyed on a literal fragment of the rule
and never on a line number, because a line number moves the moment anyone edits a rule above it and
an exemption that silently stops applying is worse than no exemption.
an exemption that silently stops applying is worse than no exemption. `stale exemptions` fails a
fragment that matches more than one rule or none, and an ambiguous fragment exempts nothing. A
`run_in_background: true` fragment once matched a swarm Phase B sentence rule as well as the token
rule it was written for, and kept that rule from failing when it went stale.

The probe's own exit status is part of the assertion for both. A probe that cannot run reports
failure, not a clean result: an empty list from a failed build is not evidence that nothing is
Expand Down
85 changes: 37 additions & 48 deletions omp-port/check-port.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,47 +37,34 @@ allow_count() { awk -F'\t' -v p="$2" '$0 !~ /^#/ && $2 == p' "$1" | wc -l; }
# the gate then goes red for a reason nobody can reconstruct. A fragment survives every edit that
# does not change the rule it names.
STALE_ALLOW="${STALE_EXEMPT:-$PORT_DIR/stale-exempt.tsv}"
exempt() {
[ -f "$STALE_ALLOW" ] || return 1
# The needle travels through the environment rather than -v, because awk applies escape
# processing to a -v assignment and a rules.sed left-hand side is full of backslashes: it would
# warn about every one of them and match the stripped text instead of the rule.
#
# Three ways a substring match can go wrong are closed here, because each one silently exempts
# more than the author intended and a wrong exemption turns the gate green, which is the exact
# failure this assertion exists to prevent:
# a whitespace-only fragment, which index() matches against almost any rule, so a stray tab
# or a double space in the file would exempt the entire table;
# a fragment too short to be distinctive, which a later rule could match by accident;
# a fragment that is only a prefix of a longer rule, which exempts that rule wholesale.
STALE_RULE="$1" awk -F'\t' '
BEGIN { rule = ENVIRON["STALE_RULE"] }
$0 !~ /^#/ {
f = $1
gsub(/^[[:space:]]+|[[:space:]]+$/, "", f)
# The length floor alone is not enough: a run of twenty spaces is twenty characters long
# and index() finds it in almost any rule, so a whitespace-only row exempts the table.
if (length(f) >= 20 && f ~ /[^[:space:]]/ && index(rule, f)) hit = 1
}
END { exit !hit }
' "$STALE_ALLOW"
}
# Every fragment has to clear the same bar the matcher enforces, so a typo is caught at review time
# rather than discovered as an exemption that quietly stopped applying.
stale_exempt_bad() {
# Resolves each exemption to the one rule it names, printing `ok<TAB><rules.sed line>` or
# `bad<TAB><why>` per entry, so the lint and the staleness check read one answer. Only a fragment
# that names exactly one rule exempts anything. A blank or short fragment is found by index() in
# almost any rule, and a fragment that matches two rules lets the one it was not written for go
# stale in silence: a `run_in_background: true` fragment once hid a swarm Phase B rule that way.
# Only a genuinely empty line is not an entry; a line holding whitespace is one, and fails.
stale_exempt_resolve() {
[ -f "$STALE_ALLOW" ] || return 0
awk -F'\t' '
$0 !~ /^#/ {
# Only a genuinely empty line is not an entry. A line holding whitespace is one, and is
# caught below: that is the shape index() would match against every rule, so skipping it
# here would reinstate the exact hole this lint exists to close.
if ($0 == "") next
FILENAME == ARGV[1] {
if ($0 ~ /^[0-9]+\t/) { n++; at[n] = $1; rule[n] = substr($0, length($1) + 2) }
else rule[n] = rule[n] "\n" $0
next
}
$0 !~ /^#/ && $0 != "" {
f = $1
gsub(/^[[:space:]]+|[[:space:]]+$/, "", f)
if (f !~ /[^[:space:]]/ || length(f) < 20)
printf " rules.sed exemption fragment is blank or under 20 chars: [%s]\n", f
if (f !~ /[^[:space:]]/ || length(f) < 20) {
printf "bad\tstale-exempt.tsv:%d fragment is blank or under 20 chars: [%s]\n", FNR, f
next
}
c = 0; hits = ""
for (i = 1; i <= n; i++) if (index(rule[i], f)) hits = hits (c++ ? ", " : "") at[i]
if (c == 1) printf "ok\t%s\n", hits
else if (c == 0) printf "bad\tstale-exempt.tsv:%d fragment matches no rule: [%s]\n", FNR, f
else printf "bad\tstale-exempt.tsv:%d fragment matches %d rules, rules.sed lines %s: [%s]\n", FNR, c, hits, f
}
' "$STALE_ALLOW"
' <(rule_records) "$STALE_ALLOW"
}
# The gate patterns live in omp-port/lib.sh, one source shared with the sync script.
pattern_for() {
Expand Down Expand Up @@ -359,6 +346,19 @@ else
report "guide claims" "PASS ${#guide_skills[@]} skills, prototype and multi-phase-plan playbooks, check-plan.mjs, Feature Map, pin"
fi

# Linted on every run, before the contracts-only exit, so a bad exemption fails the day it is
# written whether or not any rule is stale yet, and the fixture mutations can reach it.
exemptions=$(stale_exempt_resolve)
exempt_lines=$(awk -F'\t' '$1 == "ok" { print $2 }' <<<"$exemptions")
bad_frag=$(awk -F'\t' '$1 == "bad" { print $2 }' <<<"$exemptions")
if [ -n "$bad_frag" ]; then
report "stale exemptions" "FAIL"
while read -r l; do [ -n "$l" ] && violate "$l"; done <<<"$bad_frag"
violate "an exemption must name exactly one rules.sed rule by a fragment of 20 or more characters, and any other fragment exempts nothing; starting it with the rule's s# opener keeps it off other rules' replacement text"
else
report "stale exemptions" "PASS $(grep -c . <<<"$exempt_lines") fragment(s), each naming exactly one rule"
fi

if [ "${CHECK_PORT_CONTRACTS_ONLY:-}" = 1 ]; then
echo
if [ "$fail" -eq 0 ]; then echo "check-port contracts: PASS"; else echo "check-port contracts: FAIL"; fi
Expand Down Expand Up @@ -726,7 +726,7 @@ if [ "$canon_ok" = yes ]; then
unexempted=""
while IFS=$'\t' read -r n rule; do
[ -n "$n" ] || continue
exempt "$rule" || unexempted="${unexempted}rules.sed:${n}: ${rule}"$'\n'
grep -qxF "$n" <<<"$exempt_lines" || unexempted="${unexempted}rules.sed:${n}: ${rule}"$'\n'
done <<<"$stale"
total=$(grep -c . <<<"$stale" || true)
if [ -n "$unexempted" ]; then
Expand All @@ -746,17 +746,6 @@ else
report "rule staleness" "SKIP needs the clone at $CANON"
fi

# A fragment that is blank or shorter than the matcher requires exempts nothing at all, which reads
# like a working exemption and is not one. Linted separately so the mistake surfaces whether or not
# any rule is currently stale.
bad_frag=$(stale_exempt_bad)
if [ -n "$bad_frag" ]; then
report "stale exemptions" "FAIL"
while read -r l; do [ -n "$l" ] && violate "$l"; done <<<"$bad_frag"
violate "an exemption fragment that is blank or under 20 characters exempts nothing, so the rule it was written for will fail for the wrong reason"
else
report "stale exemptions" "PASS $(grep -cvE '^[[:space:]]*(#|$)' "$STALE_ALLOW" 2>/dev/null || echo 0) fragment(s), all usable"
fi
rm -rf "$scratch" "$buildlog"

echo
Expand Down
5 changes: 1 addition & 4 deletions omp-port/rules.sed
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ s#`readonly: true`#read-only posture carried in the brief#g
s#`readonly: false`#full tools per spawn#g
s#agent mode \(`readonly: false`\)#full tools per spawn#g
s#`readonly`: `true`#read-only posture carried in the brief#g
s#`run_in_background: true`#one `task` call with all items in `tasks[]`#g
s#readonly strips MCPs\.#nothing strips MCPs here.#g
# A judge is spawned with read posture in its brief, never as a field. Matched on the field name
# rather than the sentence, because upstream rewords the sentence and the field never survives it.
Expand Down Expand Up @@ -367,18 +366,16 @@ s#the `(architect|arena|swarm|interrogate) runners` line in the `pstack-models\.
s#the `interrogate reviewers` line in the `pstack-models\.mdc` rule#one exact discovered reviewer agent per configured entry#g
s#the `arena cross-judge pool` line in `~?/?\.cursor/rules/pstack-models\.mdc`#an exact discovered judge agent whose configured model differs from the parent's when the roster provides one, in `~/.omp/agent/config.yml`#g
s#the `(architect|arena|swarm|interrogate) runners` line in `~?/?\.cursor/rules/pstack-models\.mdc`#the exact discovered runner agents in `~/.omp/agent/config.yml`#g
s#the `interrogate reviewers` line in `task\.agentModelOverrides` in `~/\.omp/agent/config\.yml`#one exact discovered reviewer agent per entry in `~/.omp/agent/config.yml`#g
# The last two Cursor role labels. Same reasoning as the runner lines above: the label is a key
# in a rule file that omp does not have, so naming it names nothing. The capability it stood for
# is what the port writes instead.
s#the `how (explorer|explainer)` line#an exact discovered \1 agent in `~/.omp/agent/config.yml`#g
s#one per entry on the `interrogate reviewers` line in `~?/?(\.cursor/rules/pstack-models\.mdc|task\.agentModelOverrides in ~?/?\.omp/agent/config\.yml)`#one per configured entry in `~/.omp/agent/config.yml`#g
s#Set `model` to that line.s value, or to the default if the rule or the line is missing\.#Each discovered agent's frontmatter or `task.agentModelOverrides[<exact-name>]` selects its model; the item has no `model` field.#g
s#Leave `model` unset when the value is `auto` or `inherit-parent`\.#An `auto` or `inherit-parent` entry means the parent chat model, so omit that role from the map.#g
s#the `interrogate reviewers` line in `task\.agentModelOverrides` in `~?/?\.omp/agent/config\.yml`#one exact discovered reviewer agent per configured entry in `~/.omp/agent/config.yml`#g
s#the `interrogate reviewers` line in `~?/?\.cursor/rules/pstack-models\.mdc`#one exact discovered reviewer agent per configured entry in `~/.omp/agent/config.yml`#g
s#the `architect runners` line in the `task\.agentModelOverrides` entries in `~/\.omp/agent/config\.yml`#the same exact discovered runner agents Arena uses, with the architect role in each brief, in `~/.omp/agent/config.yml`#g
s#an exact discovered (why investigators|why synthesizer|interrogate reviewers|swarm workers|architect runners|arena runners|arena cross-judge pool|reflect tooling|reflect judgment, divergent, synthesizer) agent#an exact discovered agent filling that role#g
s#one per entry on one exact discovered reviewer agent per entry#one per configured entry#g
# A single spawn is still one task call with one item and the required shared context. Matched on
# the "spawn one <role>" phrase, which is the shape upstream uses everywhere it means one worker,
# rather than on the sentence around it.
Expand Down
14 changes: 5 additions & 9 deletions omp-port/stale-exempt.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@ The synthesizer's quality check includes spot-verifying ci superseded: upstream
there is no task `readonly` field\. Use forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
there is no task `readonly` field\.[[:space:]]*$ forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
The synthesizer returns a structured Accepted / Rejected / superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
After all Phase B candidates complete, choose an exact dis forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
s#After all Phase B candidates complete, choose an exact dis forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
^- `model`: the configured `interrogate reviewers` entry, forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
`subagent_type`: `([^`]+)` forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
`subagent_type`: `([^`]+)` forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
agent mode \(`readonly: false`\) forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
^- `readonly`: `true`$ forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
s#agent mode \(`readonly: false`\) forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
s#`run_in_background: true`#one forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
`subagent_type: "poteto-agent"` forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
s#`subagent_type: "poteto-agent"` forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
^Spawn one investigator per category that has a matching M superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
One subagent per PR, not batched, each a Cursor cloud agen superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
`claude-fable-[0-9.-]+(-(thinking-)?[a-z]+)?` forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
Expand Down Expand Up @@ -70,9 +68,7 @@ For each candidate, read the first JSONL line and check th superseded: upstream
the `arena cross-judge pool` line in the `pstack-models\.m forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
the `swarm workers` model and speed \(your fast code model forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
the `interrogate reviewers` line in the `pstack-models\.md forward-compat net: the left side is a Cursor wire token or path that upstream does not emit today. The rule earns its place by not firing, because it is the only thing standing between that text and a Cursor API in the tree.
the `interrogate reviewers` line in `task\.agentModelOverr superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
the `architect runners` line in the `task\.agentModelOverr superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
one per entry on one exact discovered reviewer agent per e superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
`agent`: an exact discovered (how explorer|how explainer) superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
re-read this playbook from trunk with `git show origin/mai superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
Re-read the execution playbook from trunk and the armed /g superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
Expand All @@ -85,8 +81,8 @@ push with `--force-with-lease` only after an `ls-remote` c superseded: upstream
The operator's full-autonomy grant plus the root's clean v superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
Recompute `frontier.json` from `gt` after every merge and superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
- Workers never rebase and never run `gt`\. superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
The strict `scout` definition has no MCP grant, so never a superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
an exact discovered full-access worker for citation spot-c superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
s#The strict `scout` definition has no MCP grant, so never a superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
s#an exact discovered full-access worker for citation spot-c superseded: upstream reworded this sentence and a different rule now covers the current phrasing. Kept because the reword is cheap for upstream to undo.
an exact discovered (why investigators|why synthesizer|interrogate reviewers second-order net: it rewrites the output of the `model`: the `<role>` line token rules, so raw upstream never matches it. At 4ec7ffa the whole-sentence rules for why and reflect claim the last role-line sentences first, so the token rules emit nothing for it to clean. Kept because a reworded sentence upstream falls through to those token rules, and this is what turns their role label into a capability.

`readonly`: `true`#read-only posture carried in the brief forward-compat net: the Cursor wire field as it appears mid-sentence rather than as a role bullet. Upstream emits no such line today; the rule is what keeps it from reaching the tree if it ever does.
Loading
Loading