Audit-filed by untether-staging monitor loop, pass 1, run 20260513T015418Z, at 2026-05-13T01:54Z.
Source: untether.service on lba-1, 0.35.3rc13.
Type: Enhancement opportunity (ENH-PATCH)
Observation:
On 2026-05-13 at 11:54:46 AEST, after a successful Claude Code run in chat -5173025382 (project auditor-toolkit, session 4e15a844-0632-477c-a9c3-c0be07573de0, 7 turns, $3.44), the outbox delivery scan logged:
2026-05-13T01:54:46.022294Z [info] outbox.skipped
branch=None chat_id=-5173025382
cwd=/home/nathan/claude-code-tools/lba/tools/auditor-toolkit/main
engine=claude project=auditor-toolkit
resume=4e15a844-0632-477c-a9c3-c0be07573de0
skipped=[('guides', 'directory')]
user_msg_id=51258
The agent had placed an item named guides (a directory) into .untether-outbox/. The outbox delivery code (outbox_delivery.py) treated directories as unsupported and dropped the entry. No surface was given to the user — the structured log is the only trace. The user finishing the run never learned the agent intended to deliver a folder.
Opportunity:
Either:
- (A) Surface the skipped item to the user. Append a single line to the final message footer:
📎 skipped (unsupported): guides (directory) or include it inline near the existing 📎 attachments block. Tells the user something was intended, prompts the agent to re-attempt with a supported approach (zip/tarball, individual files).
- (B) Auto-zip directories. On encountering a directory in the outbox, transparently
zip -r guides.zip guides/ and deliver as a single archive. Add a size cap (outbox_max_files already exists — add outbox_max_archive_bytes) and abort to (A) if too large.
(A) is cheap and unambiguous; (B) is a richer feature but adds packaging logic and a new failure surface (oversized archives, deny-globbed files inside the directory tree).
Why it matters:
- User impact: anyone whose agent generates a folder of outputs (docs, screenshots, exported reports). With workspace-mode and longer Claude/Codex runs becoming standard, agents producing folder structures is increasingly natural.
- Frequency: occasional today — agents have to be specifically prompted to deliver folders. Will rise as users get more comfortable asking agents to produce multi-file deliverables.
- Friction: silent failure. The user has no idea anything was lost. The agent's "I've prepared the guides folder for you" final message becomes a lie with no indication.
Suggested approach:
- Stage 1 — Surface (A): in
src/untether/telegram/outbox_delivery.py (scan_outbox / deliver_outbox), keep the existing outbox.skipped log line but also accumulate skipped items into a return value used by runner_bridge when composing the final message. Append a **📎 skipped:** line listing each (name, reason) pair. Add an [transports.telegram.files] config flag notify_skipped_outbox = true (default true) so users can opt out.
- Stage 2 — Optional zip (B): only after (A) ships. Add
outbox_zip_directories = false config flag (opt-in initially), use zipfile from stdlib, respect deny-globs while zipping, cap at outbox_max_archive_bytes (default 50 MiB), fall back to (A) on cap exceed.
- Update
docs/reference/transports/telegram.md outbox section.
- Tests in
tests/test_outbox_delivery.py (does this exist? tests/test_telegram_files.py covers helpers; outbox_delivery may not have a dedicated test file yet).
Related code/files:
src/untether/telegram/outbox_delivery.py (scan_outbox, deliver_outbox, the outbox.skipped log site)
src/untether/telegram/files.py (deduplication / deny-glob primitives — would be reused for zip variant)
src/untether/runner_bridge.py (final message composition)
docs/reference/transports/telegram.md (outbox docs)
untether.toml [transports.telegram.files] section
tests/test_telegram_files.py (17 tests, file helpers)
Related issues / prior conversations:
Effort estimate: S for (A) alone; M for (A)+(B).
Milestone: v0.35.4 (reasoning: small surfacing change with clear user benefit; B can defer).
— filed by untether-staging monitor loop, pass 1
Audit-filed by
untether-stagingmonitor loop, pass 1, run20260513T015418Z, at2026-05-13T01:54Z.Source:
untether.serviceonlba-1,0.35.3rc13.Type: Enhancement opportunity (
ENH-PATCH)Observation:
On 2026-05-13 at 11:54:46 AEST, after a successful Claude Code run in chat
-5173025382(projectauditor-toolkit, session4e15a844-0632-477c-a9c3-c0be07573de0, 7 turns, $3.44), the outbox delivery scan logged:The agent had placed an item named
guides(a directory) into.untether-outbox/. The outbox delivery code (outbox_delivery.py) treated directories as unsupported and dropped the entry. No surface was given to the user — the structured log is the only trace. The user finishing the run never learned the agent intended to deliver a folder.Opportunity:
Either:
📎 skipped (unsupported): guides (directory)or include it inline near the existing📎 attachmentsblock. Tells the user something was intended, prompts the agent to re-attempt with a supported approach (zip/tarball, individual files).zip -r guides.zip guides/and deliver as a single archive. Add a size cap (outbox_max_filesalready exists — addoutbox_max_archive_bytes) and abort to (A) if too large.(A) is cheap and unambiguous; (B) is a richer feature but adds packaging logic and a new failure surface (oversized archives, deny-globbed files inside the directory tree).
Why it matters:
Suggested approach:
src/untether/telegram/outbox_delivery.py(scan_outbox/deliver_outbox), keep the existingoutbox.skippedlog line but also accumulate skipped items into a return value used byrunner_bridgewhen composing the final message. Append a**📎 skipped:**line listing each (name, reason) pair. Add an[transports.telegram.files]config flagnotify_skipped_outbox = true(default true) so users can opt out.outbox_zip_directories = falseconfig flag (opt-in initially), usezipfilefrom stdlib, respect deny-globs while zipping, cap atoutbox_max_archive_bytes(default 50 MiB), fall back to (A) on cap exceed.docs/reference/transports/telegram.mdoutbox section.tests/test_outbox_delivery.py(does this exist?tests/test_telegram_files.pycovers helpers; outbox_delivery may not have a dedicated test file yet).Related code/files:
src/untether/telegram/outbox_delivery.py(scan_outbox,deliver_outbox, theoutbox.skippedlog site)src/untether/telegram/files.py(deduplication / deny-glob primitives — would be reused for zip variant)src/untether/runner_bridge.py(final message composition)docs/reference/transports/telegram.md(outbox docs)untether.toml[transports.telegram.files]sectiontests/test_telegram_files.py(17 tests, file helpers)Related issues / prior conversations:
.untether-outbox/, the original outbox feature) — CLOSED, established the mechanism. This is a follow-up gap.Effort estimate: S for (A) alone; M for (A)+(B).
Milestone:
v0.35.4(reasoning: small surfacing change with clear user benefit; B can defer).— filed by untether-staging monitor loop, pass 1