feat(publish): let one piece claim every search it answered - #178
Draft
vraspar wants to merge 1 commit into
Draft
Conversation
`tenjin publish --search-id` repeats, up to ten per piece. A research thread fans out into many searchIds, and until now the piece published back against one while the siblings were closed as `regenerated` — false twice over, and it counted every sibling of a converting loop as a MISS. Each id closes its own local loop with publish attribution (relinking one an `outcome` already closed, exactly as a single id does today), and the JSON envelope reports per id under `searches`, so an id this machine never recorded warns for itself instead of costing the others their close. A lone id keeps the flat `search` field. On the wire, one id stays the bare string it has always been and several become an array, so a single-search publish is byte-identical against a server that predates the array. Closes #167. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A1igator
added a commit
that referenced
this pull request
Aug 18, 2026
The live hosted skill moved again tonight (the #178 multi-searchId wire form), so the drift gate reddened on this branch, which merged main before the move. Mirror-only: scripts/sync-skill.mjs writes skills/tenjin/SKILL.md and nothing else, so the scan rule data, the corpus, and the tenjin-publish detector lists are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One research thread fans out into many searchIds, and a piece answers the thread rather than one query of it. A live example from 2026-08-16: one investigation logged 10 MISS searchIds for what was a single question. The piece published back against one of them, and the other nine were closed one at a time as
regenerated— false twice over, because they were not re-derived, they were answered by the same piece, and MISS-to-publish conversion counted every sibling of a converting loop as a failure.tenjin publish --search-idnow repeats, up to ten per piece.What changed
--search-idcollects (commander'scollect, the same wiring feat(outcome): batch close, and a WebSearch hook that names itself #177 gaveoutcome). Ids dedupe, each is validated againstSEARCH_ID_WIRE_REexactly as today, and the cap refuses before any wallet touch.closeNamedSearchruns once per id with unchanged relink semantics: a loop anoutcomealready closed is taken over, a loop an earlier publish claimed reportsalreadyAnswered, and an id absent from the local store warns for itself rather than costing the others their close. Results land per id in the JSON envelope undersearches, one human line each. A lone id keeps the flatsearchfield callers have read since Publish-back loop DX: no defer status, invisible publish.mode, lost --search-id linkage (agent session trace) #161.questionsAnsweredis prefilled from the first named search this machine has a record of; the rest are attribution, not phrasing. Each receipt says which id supplied it.--draftanswers nobody however many searches it names, so it sends nosearchIdat all and leaves every loop open.tenjin_publishtakessearchIdas a string or an array, matching what feat(outcome): batch close, and a WebSearch hook that names itself #177 did for the outcome tool.Wire shape, and the deploy ordering
A lone id stays the bare string, so a single-search publish keeps working against a post-create that only takes a scalar. The array form requires the sibling tenjin PR (branch
vraspar/post-lookups-multi-searchid) deployed first — an array against the current validator is a hard 400. The changeset states the same ordering.The committed OpenAPI fixture still declares the scalar, so
contract.test.tscontinues to pin the single-id body against it; the array is pinned at the builder inposts-api.test.tsinstead.Rejected alternatives, honored
Per #167, none of these are here and none should arrive later: no similarity auto-linking (false links poison outcome data), no close-all-session-MISSes on publish (one session holds unrelated investigations), no explicit thread handles on searches.
Scope
The outcome half of #167 shipped separately in #177 (
tenjin outcome --search-idrepeating, plus--all-open). This PR is the publish half and closes the issue. Nothing here touches ephemeral status or the auto-sweep, which belong to the other train.Design record:
tenjin-notes/plans/2026-08-17-outcome-taxonomy-and-167.md, "Closing #167".Closes #167.
Tests
New coverage in
src/commands/publish.test.ts,src/lib/posts-api.test.ts, andsrc/cli.test.ts: the dispatcher collects rather than replacing (read back through the cap, which only eleven surviving ids can trip); the wire carries an array for several ids and a bare string for one; repeats collapse on the wire and in the ledger; the cap refuses before the keystore opens; a mix of closeable, relinked, already-answered, and absent ids each reports honestly; the prefill names its source; a multi-id draft sends nothing.pnpm typecheck,pnpm lint, andprettier --checkare clean. Full vitest run: 2148 passed, 2 failed — both pre-existing indoctor.test.tson this machine and reproduced identically atorigin/main(they read the developer's real installed skills state).🤖 Generated with Claude Code