Files
strukto-ai--mirage/integ/resources/discord/ops.json
T
bytecii 73f5bd7c21 chore: cleanup items 31+32 — nested-function rule, layout, CI audit, ls facets
Closes the two remaining small items of Block E. Both were largely
recon: much of what they filed had already been fixed, and the part
that had not turned up a real GNU divergence.

Item 31 (T3-7), rule/doc reconciliation
---------------------------------------

The `object`-parameter half is already done: #825's mypy inversion took
the package from the filed 28 down to 7, of which 3 are docstring prose
and the remaining 4 are protocol methods (`__contains__`, `pop`) whose
signatures typeshed dictates, all already listed in the no-object gate.
`utils/errors.py` reads `str | PathSpec` today, and `builders/sed.py` no
longer holds flag values at all -- item 22 moved that to the generic.

That left the nested-function rule, which the plan asked to decide
before gating. Measured: 39 nested defs, and **every one of them closes
over its enclosing scope** -- 38 by free variable, and `sed_helper._repl`
by binding through parameter defaults, the loop-variable idiom, with a
comment saying so. A flat "do not nest" is a rule the architecture
cannot keep (op factories, provision builders, the read-through cache,
every decorator's wrapper), so gating it as written would have meant 39
standing violations.

So the rule now says what it was reaching for: a nested def must capture
the scope around it, or it belongs at module level. That is mechanical
and enforceable -- `tests/test_nested_functions_are_closures.py` reads
free variables from `symtable` and parameter defaults from the AST. It
passes on the tree as-is and fires on a helper that reads only its own
arguments.

Layout: the eight test-only TS directories are flattened
(`ram/{cat,cut,grep,head,ls,tail,wc}/`, `ssh/ls/`), `awk_helper.ts` moves
up beside its nine siblings, and the `provision.ts` / `_provision.ts`
split is settled on Python's convention -- `_provision` for a backend's
own, bare `provision` for the shared ones (cli, generic_bind). That last
one was not cosmetic: Python already had `_provision.py` for github,
gmail, redis and email, so renaming **closed 4 real parity divergences**
(layout baseline 296 -> 292). The `findEval`/`findParse` line was
already done in #827.

Item 32 (T3-8), test/CI tidiness
--------------------------------

The two asymmetric `ls` conformance matrices are raised to symmetry, and
they pass: python `[ram,disk,redis]` vs typescript `[ram]` was stale
caution, not a divergence. Both runners now reject an asymmetric matrix
at load time unless the case carries a `divergence` key explaining why --
a case is a parity claim, and narrowing one side reads as coverage while
the side that still lists the backend goes green. Loading the corpus
under the new assertion proves no other case was asymmetric. The README
documented the override as "not yet needed"; it exists now.

Adds the `ts-audit` job, mirroring `test_python.yml`'s exactly (same
`continue-on-error`, same out-of-gate placement). Nothing ran `pnpm
audit` for the TS tree while `typescript/package.json` carried 27
hand-written CVE overrides that only a person remembering to check kept
current.

Integ facets for `ls`: `-A`, `-d`, `-r`, `-S`, `-h`, all pinned against
GNU coreutils 9.7 in docker. `-S` uses regular files only, because GNU
sorts a directory by its inode size while mirage counts it as 0 -- a
divergence CLAUDE.md documents deliberately.

The `-h` facet found a real bug
-------------------------------

`ls -h` disagreed with GNU three ways, and because the flag had zero
cross-backend coverage nothing caught it. GNU prints a count below one
unit with no suffix (`24`); mirage printed `24B`. GNU rounds *up* to the
precision shown (1025 bytes is `1.1K`); mirage gave `1.0K`. GNU drops
the decimal once the value reaches ten (`10K`); mirage gave `10.0K`.

One shared engine replaces both formatters in both languages -- GNU runs
`-h` and `-H` through one `human_readable`, and so do we now. Rounding
up can carry past the base (1048575 ceils to 1024K, which GNU shows as
`1.0M`), so the unit is re-chosen after rounding rather than once up
front. 21 GNU-read points are pinned as a table in each language.

Blast radius, all re-pinned: five integ cases that had recorded the `B`
suffix (du, discord, langfuse, email, gmail), and the du fan-out tests.
Those last ones needed care rather than a new number: they exist to
prove the total is humanized once instead of twice, and their 1500+1500
stops discriminating under correct rounding, since 3000 bytes and two
`1.5K` readings both render `3.0K`. They now use 1025+1025, where
single-rounding gives `2.1K` and double-rounding would give `2.2K`.

Verified: pre-commit clean, integ 8054/0 on ram+disk+redis in both
languages, conformance green in both, and the layout, spec, barrel,
docs, case-target and PathSpec gates all pass.

Not covered, still open on item 32: integ facets for `ls -t` (mtime
order is not stable across backends without a seeded fixture), mktemp,
gzip, the checksum `--check` companions, `df -H/-k/-a`, and `cmp
-n/-b/-i`; and the T2-7 helper unit-suite mirroring. Item 31 leaves the
provision *presence* sets unreconciled (Python has lancedb/qdrant, TS has
trello) -- that is a question about which backends should provision at
all, not about naming.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 06:57:08 -07:00

369 lines
10 KiB
JSON

{
"cases": [
{
"id": "dc_ls_root",
"seq": 690000,
"targets": [
"discord"
],
"command": "ls /discord",
"expect": {
"exit": 0,
"stdout": "Mirage HQ__100000000000000001\n",
"stderr": ""
}
},
{
"id": "dc_ls_guild",
"seq": 690001,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001'",
"expect": {
"exit": 0,
"stdout": "channels\nmembers\n",
"stderr": ""
}
},
{
"id": "dc_ls_channels",
"seq": 690002,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/channels'",
"expect": {
"exit": 0,
"stdout": "general__200000000000000001\nreleases__200000000000000002\n",
"stderr": ""
}
},
{
"id": "dc_ls_members",
"seq": 690003,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/members'",
"expect": {
"exit": 0,
"stdout": "alice__300000000000000001.json\nbob__300000000000000002.json\nmirage-bot__900000000000000001.json\n",
"stderr": ""
}
},
{
"id": "dc_ls_dates_count",
"seq": 690004,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001' | wc -l",
"expect": {
"exit": 0,
"stdout": "30\n",
"stderr": ""
}
},
{
"id": "dc_ls_dates_tail",
"seq": 690005,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001' | tail -3",
"expect": {
"exit": 0,
"stdout": "2026-05-31\n2026-06-01\n2026-06-02\n",
"stderr": ""
}
},
{
"id": "dc_ls_day",
"seq": 690006,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01'",
"expect": {
"exit": 0,
"stdout": "chat.jsonl\nfiles\n",
"stderr": ""
}
},
{
"id": "dc_ls_files",
"seq": 690007,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files'",
"expect": {
"exit": 0,
"stdout": "budget__500000000000000001.csv\n",
"stderr": ""
}
},
{
"id": "dc_cat_day_content",
"seq": 690008,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/chat.jsonl' | jq -r .content",
"expect": {
"exit": 0,
"stdout": "deploy is green\nthanks alice, shipping the release notes\nbudget spreadsheet attached\n",
"stderr": ""
}
},
{
"id": "dc_cat_day_authors",
"seq": 690009,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/chat.jsonl' | jq -r .author.username",
"expect": {
"exit": 0,
"stdout": "alice\nbob\nalice\n",
"stderr": ""
}
},
{
"id": "dc_cat_second_day",
"seq": 690010,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-02/chat.jsonl' | jq -r .content",
"expect": {
"exit": 0,
"stdout": "second day standup\n",
"stderr": ""
}
},
{
"id": "dc_cat_other_channel",
"seq": 690011,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/releases__200000000000000002/2026-06-01/chat.jsonl' | jq -r .content",
"expect": {
"exit": 0,
"stdout": "v1.2.0 released\n",
"stderr": ""
}
},
{
"id": "dc_cat_member",
"seq": 690012,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/members/alice__300000000000000001.json' | jq -r '.nick + \" \" + .user.username'",
"expect": {
"exit": 0,
"stdout": "al alice\n",
"stderr": ""
}
},
{
"id": "dc_cat_attachment",
"seq": 690013,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files/budget__500000000000000001.csv'",
"expect": {
"exit": 0,
"stdout": "quarter,amount\nQ1,100\nQ2,250\n",
"stderr": ""
}
},
{
"id": "dc_wc_lines",
"seq": 690014,
"targets": [
"discord"
],
"command": "wc -l < '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/chat.jsonl'",
"expect": {
"exit": 0,
"stdout": "3\n",
"stderr": ""
}
},
{
"id": "dc_head_attachment",
"seq": 690015,
"targets": [
"discord"
],
"command": "head -c 20 '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files/budget__500000000000000001.csv'",
"expect": {
"exit": 0,
"stdout": "quarter,amount\nQ1,10",
"stderr": ""
}
},
{
"id": "dc_du_day",
"seq": 690016,
"targets": [
"discord"
],
"command": "du -s '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-02'",
"expect": {
"exit": 0,
"stdout": "374\t/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-02\n",
"stderr": ""
}
},
{
"id": "dc_du_files",
"seq": 690017,
"targets": [
"discord"
],
"command": "du -sh '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files'",
"expect": {
"exit": 0,
"stdout": "29\t/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files\n",
"stderr": ""
}
},
{
"id": "dc_find_type_f",
"seq": 690018,
"targets": [
"discord"
],
"command": "find '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01' -type f | sort",
"expect": {
"exit": 0,
"stdout": "/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/chat.jsonl\n/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files/budget__500000000000000001.csv\n",
"stderr": ""
}
},
{
"id": "dc_find_type_d",
"seq": 690019,
"targets": [
"discord"
],
"command": "find '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01' -type d | sort",
"expect": {
"exit": 0,
"stdout": "/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01\n/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files\n",
"stderr": ""
}
},
{
"id": "dc_grep_count",
"seq": 690020,
"targets": [
"discord"
],
"command": "grep -c release '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/chat.jsonl'",
"expect": {
"exit": 0,
"stdout": "1\n",
"stderr": ""
}
},
{
"id": "dc_grep_files_with_match",
"seq": 690021,
"targets": [
"discord"
],
"command": "grep -l standup '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-02/chat.jsonl'",
"expect": {
"exit": 0,
"stdout": "/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-02/chat.jsonl\n",
"stderr": ""
}
},
{
"id": "dc_tree_members",
"seq": 690022,
"targets": [
"discord"
],
"command": "tree '/discord/Mirage HQ__100000000000000001/members'",
"expect": {
"exit": 0,
"stdout": "/discord/Mirage HQ__100000000000000001/members\n|-- alice__300000000000000001.json\n|-- bob__300000000000000002.json\n`-- mirage-bot__900000000000000001.json\n\n1 directory, 3 files\n",
"stderr": ""
}
},
{
"id": "dc_stat_day_type",
"seq": 690023,
"targets": [
"discord"
],
"command": "stat -c %F '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01'",
"expect": {
"exit": 0,
"stdout": "directory\n",
"stderr": ""
}
},
{
"id": "dc_stat_attachment_type",
"seq": 690024,
"targets": [
"discord"
],
"command": "stat -c %F '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/files/budget__500000000000000001.csv'",
"expect": {
"exit": 0,
"stdout": "regular file\n",
"stderr": ""
}
},
{
"id": "dc_ls_missing",
"seq": 690025,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/nope'",
"expect": {
"exit": 2,
"stdout": "",
"stderr": "ls: cannot access '/discord/Mirage HQ__100000000000000001/nope': No such file or directory\n"
}
},
{
"id": "dc_cat_missing",
"seq": 690026,
"targets": [
"discord"
],
"command": "cat '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/nope.jsonl'",
"expect": {
"exit": 1,
"stdout": "",
"stderr": "cat: '/discord/Mirage HQ__100000000000000001/channels/general__200000000000000001/2026-06-01/nope.jsonl': No such file or directory\n"
}
},
{
"id": "dc_ls_file_operand",
"seq": 690027,
"targets": [
"discord"
],
"command": "ls '/discord/Mirage HQ__100000000000000001/members/alice__300000000000000001.json'",
"expect": {
"exit": 0,
"stdout": "/discord/Mirage HQ__100000000000000001/members/alice__300000000000000001.json\n",
"stderr": ""
}
}
]
}