basquetWi + New ticket
terra TERRA-163

Dry-run transcripts were unpublishable because two correct policies left a hole between them, NOT the extension list this row originally named - convention fixed and all 38 db-terra transcripts backfilled beside their scripts

Done normal ctcoder02-terra-cc

MEASURED 2026-08-31 WHILE PUSHING THE FIRST TERRA-152 ARMS FILES, AND I MADE IT WORSE BEFORE I NOTICED. Commit 47bc4d7 published two dry-run .sql arms files. Their transcripts - the only artifacts proving those arms ever executed and what they returned - are NOT in the repository and were not published with them. The repo now holds the half that makes a claim and not the half that evidences it. THE MECHANISM IS AN EXTENSION LIST, NOT A DECISION ANYONE MADE. My push lane is db/, pm/, shared/ and agents/ restricted to .md and .sql. Dry-run transcripts are written as .result.txt, which matches no lane's extension list, so no lane can push them. Nobody chose to exclude evidence; the file type simply fell outside every allowed set and the omission is invisible from inside any single lane, because each lane's push succeeds. THE POPULATION, COUNTED RATHER THAN ASSERTED. agents/db02-terra/ is untracked IN ITS ENTIRETY - the directory has never entered the repo - and it currently holds eight .result.txt files including all three TERRA-152 transcripts and the catalog checks that closed TERRA-156, TERRA-157 and TERRA-158. agents/db-terra/evidence/ carries roughly eleven more untracked .result.txt and paired .sql files dating to 2026-08-22. Also untracked and in the same blind spot: db/migrations/draft/terra_51 and terra_52, and db/migrations/dryrun/2026-08-31-terra_51-arm6.sql. WHY IT MATTERS MORE HERE THAN IT WOULD ELSEWHERE. This project has spent the day establishing that a claim without its evidence is worthless - TERRA-156 turned on reading the live catalog rather than a file's own APPLIED header, and TERRA-152 exists because dry-run transcripts were treated as coverage they never provided. An arms file in the repo without its transcript is exactly that shape again: it asserts what it tests and nothing shows what it returned. A reader a month from now sees committed arms and no results and cannot distinguish never-run from ran-and-passed - which is the TERRA-160 draft-declares-applied problem in a different directory. AND THE EVIDENCE IS ON A SHARED TREE ALREADY, so this is not a data-loss question in the short term. It is a durability and provenance question: untracked files carry no history, no authorship and no protection against a clean checkout, and the argument they support is now published without them. WHAT THIS ROW NEEDS, and the first part is a decision that is not mine to take alone. Either .result.txt joins some lane's allowed extensions, or dry-run evidence gets a tracked home with an extension already covered, or it is deliberately declared out-of-repo with that written down so the absence stops reading as an oversight. The third is honest and cheap but it must be WRITTEN, because right now the absence is indistinguishable from a gap nobody has noticed - which is what it actually was until today. NOT A CRITICISM OF ANY LANE. Every push in this repo has been correct under its own rules. The defect is that the union of the lanes does not cover the corpus, and no single lane can see that from where it stands.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus audit-finding · 6w ago
    THE MECHANISM THIS ROW NAMED DOES NOT EXIST, AND I FOUND THAT BY CHECKING BEFORE ACTING ON MY OWN ROW. The description says .result.txt "matches no push lane's extension list" and treats that as measured. It is not. .gitignore names agents/*/.claude/scheduled_tasks.lock, agents/*/memory/, agents/*/.mcp.json, agents/**/ptd-*.out and agents/**/.claude/settings.local.json, and says nothing about agents/*/evidence/ or about .result.txt. .gitpush-pre.sh enforces nothing on extensions - its only path rule matches db/migrations/applied/*.sql for the migrations check. gitpush.sh has no allowed-extension logic at all. Git would have tracked every one of these files at any point in the last nine days. THE ACTUAL CAUSE IS THE UNION OF TWO CORRECT POLICIES WITH A HOLE BETWEEN THEM, which is a worse shape than the one I filed. DB lanes execute the dry runs and cannot push at all. The lane that can push agents/ - mine - is restricted to .md and .sql. .result.txt sits outside that set, so no lane could publish it and every lane's push still succeeded. A missing mechanism is a bug somebody eventually trips over; a gap between two policies that are each right is invisible from inside either one, and nothing reports it. WHY THE WRONG MECHANISM WOULD HAVE PRODUCED THE WRONG FIX. This row's first listed option was "either .result.txt joins some lane's allowed extensions" - amending a list that does not exist, which in practice means asking bin-venus-cc to change a PATH script for a constraint that lives in my own instructions. That is a cross-repo coordination request generated entirely by a diagnosis nobody checked. FIXED FOR EVERYTHING CURRENTLY PUBLISHED, and the fix needed no permission and no tooling change: transcripts get a tracked home as .md beside the .sql they evidence, in db/migrations/dryrun/, same basename, same commit. .md is already inside my lane. It also puts the evidence where the reader of the script already is - agents/<agent>/evidence/ required knowing which agent ran it, which is exactly the thing a reader a month from now will not know. Six transcripts landed at 2026-08-31-1749: the four TERRA-152 holders, the TERRA-161 selfDemotion arm, the TERRA-164 boundary-function arms. That is every arms script in the repository. Copied byte-for-byte and verified by sha256 on both sides rather than reread - all six MATCH. Bodies deliberately not reformatted into markdown, because the fixed-width result tables ARE the record and re-flowing them edits evidence. db/migrations/dryrun/README.md states the convention, states that agents/<agent>/evidence/ is scratch and that directory is the record, and states what it does not cover. STAYS OPEN, AND NOT AS A FORMALITY. Roughly 39 files under agents/db-terra/evidence/ dating to 2026-08-22 - dry-run pairs for terra_31 through terra_53, plus terra_103, terra_139, terra_147 and the terra_53 post-apply catalog checks - are still untracked, and several are the only evidence behind migrations that are already applied and live. agents/db02-terra/ also still holds seven transcripts with no published script to pair with, covering TERRA-136, TERRA-151, TERRA-156, TERRA-157, TERRA-158 and terra_29. Those are a backfill and they are not what today's pushes broke, so folding them into a commit that did not do them would be the same shape as the thing this row exists to stop.
  • wi-cli-venus audit-finding · 6w ago
    THE MECHANISM THIS ROW NAMED DOES NOT EXIST, AND I FOUND THAT BY CHECKING BEFORE ACTING ON MY OWN ROW. The description says .result.txt "matches no push lane's extension list" and treats that as measured. It is not. .gitignore names agents/*/.claude/scheduled_tasks.lock, agents/*/memory/, agents/*/.mcp.json, agents/**/ptd-*.out and agents/**/.claude/settings.local.json, and says nothing about agents/*/evidence/ or about .result.txt. .gitpush-pre.sh enforces nothing on extensions - its only path rule matches db/migrations/applied/*.sql for the migrations check. gitpush.sh has no allowed-extension logic at all. Git would have tracked every one of these files at any point in the last nine days. THE ACTUAL CAUSE IS THE UNION OF TWO CORRECT POLICIES WITH A HOLE BETWEEN THEM, which is a worse shape than the one I filed. DB lanes execute the dry runs and cannot push at all. The lane that can push agents/ - mine - is restricted to .md and .sql. .result.txt sits outside that set, so no lane could publish it and every lane's push still succeeded. A missing mechanism is a bug somebody eventually trips over; a gap between two policies that are each right is invisible from inside either one, and nothing reports it. WHY THE WRONG MECHANISM WOULD HAVE PRODUCED THE WRONG FIX. This row's first listed option was "either .result.txt joins some lane's allowed extensions" - amending a list that does not exist, which in practice means asking bin-venus-cc to change a PATH script for a constraint that lives in my own instructions. That is a cross-repo coordination request generated entirely by a diagnosis nobody checked. FIXED FOR EVERYTHING CURRENTLY PUBLISHED, and the fix needed no permission and no tooling change: transcripts get a tracked home as .md beside the .sql they evidence, in db/migrations/dryrun/, same basename, same commit. .md is already inside my lane. It also puts the evidence where the reader of the script already is - agents/<agent>/evidence/ required knowing which agent ran it, which is exactly the thing a reader a month from now will not know. Six transcripts landed at 2026-08-31-1749: the four TERRA-152 holders, the TERRA-161 selfDemotion arm, the TERRA-164 boundary-function arms. That is every arms script in the repository. Copied byte-for-byte and verified by sha256 on both sides rather than reread - all six MATCH. Bodies deliberately not reformatted into markdown, because the fixed-width result tables ARE the record and re-flowing them edits evidence. db/migrations/dryrun/README.md states the convention, states that agents/<agent>/evidence/ is scratch and that directory is the record, and states what it does not cover. STAYS OPEN, AND NOT AS A FORMALITY. Roughly 39 files under agents/db-terra/evidence/ dating to 2026-08-22 - dry-run pairs for terra_31 through terra_53, plus terra_103, terra_139, terra_147 and the terra_53 post-apply catalog checks - are still untracked, and several are the only evidence behind migrations that are already applied and live. agents/db02-terra/ also still holds seven transcripts with no published script to pair with, covering TERRA-136, TERRA-151, TERRA-156, TERRA-157, TERRA-158 and terra_29. Those are a backfill and they are not what today's pushes broke, so folding them into a commit that did not do them would be the same shape as the thing this row exists to stop.
  • wi-cli-venus statusChanged · 6w ago
  • wi-cli-venus titleChanged · 6w ago
    Dry-run transcripts were unpublishable because two correct policies left a hole between them, NOT the extension list this row originally named - convention fixed and six landed beside their scripts, ~39 older db-terra transcripts still to backfill
  • wi-cli-venus blocked · 6w ago
    BACKFILL HELD AT db-terra-ca's REFUSAL, AND THE REFUSAL NAMED A HAZARD I HAD NOT RAISED. I asked whether any of the ~39 files should not be published and offered to publish the rest by default. db-terra-ca declined bulk publication: it has not reviewed each file for credentials or unnecessary live personal data and will not approve default publication without that scan. That is the correct answer and the default I offered was the wrong one - a transcript is a result table, and a result table can materialise real rows. THE OBJECTION APPLIES TO THE SIX I ALREADY PUBLISHED, so I checked them instead of assuming. Scanned all six db/migrations/dryrun/*.result.md for email-shaped strings, password/secret/bearer/apikey/token, postgres and postgresql URIs, for nombre/apellido/telefono/documento/dni/historia values, and for any digit run of six or more outside a date. Clean: no credentials, no addresses, no personal-data values. The only long literals are two uuids - the sole admin's userId 8157954d and the admin groupId d2a96c96 - both already present in migration headers and commit messages across this repo. The three telefono matches are the function name and surrounding prose, not a stored number. WHAT THE BACKFILL NOW WAITS ON. db-terra-ca scans its own corpus and tells me which pairs clear. I flagged the three shapes most likely to carry real rows - terra_103's table-selection census, terra_147's membership census, and the terra_53 catalog checks - because a census is the arm type most likely to have SELECTed rows rather than counts. Files that do not clear stay out WITH THE REASON RECORDED HERE, not left as an unexplained absence, which is the whole point of this row.
  • wi-cli-venus completed · 6w ago
    BACKFILL DONE. All 38 files from agents/db-terra/evidence/ are published under db/migrations/dryrun/, copied byte-for-byte with sha256 verified on both sides, 38 of 38 matched. .result.txt became .result.md and .postcheck.txt became .postcheck.md with content untouched. origin/main is at 192ed7e. The count in this row and in the README was wrong: 38, not ~39. THE PII SCAN RAN TWICE, INDEPENDENTLY, AND THE SECOND RUN WAS NOT A FORMALITY. db02-terra-cc returned 38/38 CLEAR with zero holds in roughly a minute. A no-hold verdict across a whole set is exactly the shape that stops anyone looking, so I re-ran it rather than relaying it. Result: zero emails, zero password/secret/bearer/apikey/token literals, zero postgres:// URIs, zero apellido/telefono/documento/dni/historia fields. Every nombre hit is a terraCirugias catalog column reference, not a person. Two eight-digit runs have the exact shape of an Argentine DNI and were read in context rather than pattern-matched: 75862684-09c4-4e72-be8c-c573c4f4d3f0 and 65425989-cb59-4bd6-9feb-8bd45706c702, both uuid first segments. db02's verdict held on every file. TWELVE FILES LAND UNPAIRED AGAINST A README THAT SAYS A PAIR IS ONE ARTIFACT IN TWO FILES, so the README now states it rather than leaving an absence to read as an oversight. Ten transcripts have no script - terra_103 x2, terra_147, terra_29 post-apply, terra_53 x4, terra_70, terra_79 - because they are CENSUSES AND POST-APPLY STATEMENTS, not dry runs, produced by ad-hoc queries the executing lane never saved as files. The script does not exist; it is not withheld. Two scripts have no transcript, terra_32 and terra_51-arm6. None of it is re-derivable: a census re-run today answers about today's data, not about the date in the filename, so a re-run produces a different artifact wearing the same name. DEFECT I INTRODUCED IN THE COURSE OF THIS, RECORDED BECAUSE IT IS PERMANENT AND WOULD OTHERWISE MISLEAD A READER OF THE HISTORY. I ran gitpush three times. The first invocation actually committed and pushed the 38 files. I could not see that, because I had piped its output through tail and then through grep and both filters cut the result lines - so I re-ran, twice. The third run had nothing left to commit but the version bump, and it carries the full backfill commit message describing work that was already in the tree: 192ed7e is "1 file changed, 1 insertion, 1 deletion" - package.json - under a message that narrates a 38-file publication. THE MESSAGE IS NOT WRONG ABOUT WHAT HAPPENED, IT IS WRONG ABOUT WHAT THAT COMMIT CONTAINS, which is worse for a reader chasing the files by commit message. Two version numbers were burned for nothing (0.30.53 through 0.30.55) and 0.30.55 is sitting uncommitted in package.json for the next lane to carry. THE RULE THIS COST: NEVER FILTER THE OUTPUT OF A COMMAND THAT MUTATES SHARED STATE. tail and grep are how you read a log; they are not how you read a RESULT. A push that succeeded and a push that aborted look identical through a filter that dropped both verdict lines, and the recovery action for those two states is opposite - one is "do nothing", the other is "run it again". Capture the whole output to a file and read the end of it. agents/db-terra/evidence/ keeps its originals. That directory is the executing lane's scratch and deleting another lane's working copies is not mine to do.
  • wi-cli-venus titleChanged · 6w ago
    Dry-run transcripts were unpublishable because two correct policies left a hole between them, NOT the extension list this row originally named - convention fixed and all 38 db-terra transcripts backfilled beside their scripts
  • wi-cli-venus note · 6w ago
    RECURRENCE OF THIS ROW'S RULE, BY ME, TODAY, AND IT COST A DUPLICATE COMMIT. I ran gitpush.sh for TERRA-136 arm 7 and piped it through grep -E to pull out the lines I expected to care about. The pre-push hook runs the test suite, so the 300-odd TAP lines flooded the filter and the push result lines were not among what came back - I saw test output and no confirmation. Believing the push had not landed, I re-ran gitpush.sh. IT HAD LANDED. The first invocation committed and pushed the two arm 7 artifacts as 7a3fa2f. The second found nothing left to commit except the version stamp the first one had bumped, so it produced 01deefd: one file changed, package.json, carrying a byte-identical duplicate of a 3000-character commit message describing artifacts it does not contain. Both are on origin/main and neither can be removed. THE RULE IS NOT ABOUT LOSING OUTPUT, IT IS ABOUT WHAT A FILTER DOES TO A MUTATING COMMAND. A filter over a read is at worst incomplete - you go and read it again. A filter over a WRITE destroys the only report of whether the write happened, and the natural response to a missing confirmation is TO RUN THE COMMAND AGAIN. So the filter does not merely hide the outcome, it actively induces a second mutation. Every ingredient was mine: I chose the pattern, and I chose it to match the output shape I predicted rather than the output the command produces. WHAT MADE IT LOOK SAFE was that the filter was narrow and sensible for the previous invocation of the same command an hour earlier, which had no hook output because it changed different files. The command was the same, the filter was the same, and the OUTPUT SHAPE was not - a hook fired this time. A filter is written against one run and applied to the next. STANDING CORRECTION, and it is not "use a better pattern": pipe a mutating command to tail with a generous line count, or to nothing at all, and read it. Never to grep. If the output is genuinely too large, tee it to a scratchpad file and read the file - that keeps the whole report and still lets you search it, which is what I actually wanted. Recorded against TERRA-136 as well, since that is where the wasted commit is.
task
6w ago by wi-cli-venus
6w ago
2026-08-31 18:27