fix(next): label line 1 only when line 1 is the title - #232
Merged
gcko merged 1 commit intoAug 27, 2026
Merged
Conversation
`nextSessionRow` builds line 1 as `session.title || session.last_prompt || ""` but gated the `title:` label on line 2 existing, so the label made a claim line 1's own data need not support. Two ways: it captioned an unfiltered `last_prompt` as a title, and with neither field present it rendered a dangling `title: ` above a populated line 2 — `nextInstructionEchoes` returns false on an empty head, so nothing else suppressed the line beneath it. The gate is now a conjunction rather than a replacement, because the existing rule is also right and had to survive: a row with no line 2 still takes no label, since the label exists only to tell the two lines apart and the column is already headed SESSION. Measured before changing anything. Over 3,774 local Claude transcripts and 459 Codex rollouts, the precondition occurs 0 times and the sets are NESTED: all 1,820 Claude transcripts publishing an instruction also publish a title, and all 51 Codex ones do. So this is behaviour-neutral on every row that exists today, and the test has to construct the state rather than find it. It is worth closing anyway because the containment is a property of the corpus on Claude and of the code only on Codex. Codex derives title, last_prompt and instruction from one `codex_instruction` call, so they cannot disagree. Claude derives them from independent reads: `last_prompt` needs a `last-prompt` record inside the bounded tail while `session_instruction` walks the whole file backward, and `session_title` falls back to `prompt_title` of the FIRST prompt-signal record and breaks whatever that returns. An opening prompt that strips to empty above a genuine later one produces the state, and 386 of 386 local image markers strip to empty. The conjunction makes it unrepresentable instead of unlikely. Out of scope deliberately: whether a raw `last_prompt` on line 1 deserves a label of its own. 0 rows would show one, and a new label vocabulary entry on no evidence is speculation. Byte pins recomputed from the assets: next-sessions.js 4,557 -> 5,346 and the assembled next page 231,321 -> 232,110. The two deltas are both 789, which is the cross-check that nothing else moved underneath. Closes DRC-4270 Signed-off-by: Jared Scott <jared.scott@variable.team>
Contributor
CoverageThreshold: |
gcko
deleted the
feature/drc-4270-the-sessions-table-title-label-can-render-with-nothing-after
branch
August 27, 2026 23:38
gcko
added a commit
that referenced
this pull request
Aug 28, 2026
…sync marker (#234) Two loose ends from cutting v0.17.0, the first real run of `cargento-release`. Step 5 said `git tag "v$VERSION"`. On a machine with `tag.gpgsign true` that tries to create a signed tag, finds no message, and dies with `no tag message?` before anything reaches the remote. It failed on the release it was written for. The fix is `git -c tag.gpgsign=false`, which forces the lightweight form. That is what this repository's release tags are (`git cat-file -t v0.16.0` prints `commit`, not `tag`) and it is what the workflow's own `git tag -f` re-creates when it moves the tag onto the bump commit, so the override matches the end state rather than working around it. Where signing is off it does nothing. A `git cat-file -t` check rides along because the wrong outcome is silent in the other direction: an annotated tag pushes fine and the mismatch only shows up later. Rehearsed this time rather than reasoned about: created a throwaway tag locally, confirmed `commit`, deleted it, and confirmed the bare form still fails. The comment in the skill records why that rehearsal is possible and why the original command was the one that went untested. Also stamps `docs-synced-through` from `0f9d086` to `ec10918`, per AGENTS.md's rule to advance it once from main after merges rather than per branch. The range covers four commits: the previous stamp (#231), the sessions-table title label (#232), the `cargento-release` skill itself (#233), and the v0.17.0 release bump. Signed-off-by: Jared Scott <jared.scott@variable.team>
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.
Closes DRC-4270 (DRC-4269 finding C1, deferred from #228).
The defect
nextSessionRowbuilds line 1 assession.title || session.last_prompt || ""but gated thetitle:label on line 2 existing. The label therefore made a claim about line 1 that line 1's own data need not support:last_promptas a title, andtitle:above a populated line 2, becausenextInstructionEchoesreturnsfalseon an empty head and nothing else suppressed the line beneath it.The fix is a conjunction, not a replacement. The existing rule at
next-sessions.js:67-71is also right and had to survive: a row with no line 2 still takes no label, since the label exists only to tell the two lines apart and the column is already headed SESSION.What the measurement says
I measured before changing anything, and it reframes the issue. Counts only.
The sets are nested, not coincidentally disjoint: every transcript that publishes an instruction also publishes a title. 36 Claude transcripts have no title and none of them carry an instruction. Codex publishes only the
agent(43) andearlier(8) labels, neverasked. Published payload today is 6 rows, 3 carrying an instruction, 0 defective.So this change is behaviour-neutral on every row that exists today, and the test has to construct the state rather than find it.
Why close it anyway
The containment is a property of the corpus on Claude and a property of the code only on Codex.
Codex derives
title,last_promptandinstructionfrom onetranscripts.codex_instructioncall, so they cannot disagree about whether the read happened.Claude derives them from genuinely independent reads.
last_promptneeds atype: "last-prompt"record inside the bounded tail (claude_data.py:337);session_instructionwalks the whole file backward over"user"records. Andsession_titlefalls back toprompt_titleof the first prompt-signal record andbreaks whatever that returns (claude_data.py:161-162). An opening prompt that strips to empty above a genuine later one produces the state — and 386 of 386 local image markers strip to empty (DRC-4269 item 4.10).The conjunction makes the state unrepresentable rather than unlikely, so nobody has to re-derive this argument.
Out of scope, deliberately
Whether a raw
last_prompton line 1 deserves a label of its own (last prompt, say). 0 rows would show one, and adding a label vocabulary entry on no evidence is the speculative half of the issue.Verification
The new test fails against
mainshowing the defect verbatim —title</span>: Deploy the staging storecaptioning a raw prompt — and passes here. One assertion of my own was replaced during review of my own work:<strong></strong>would have passed for free because the live dot occupies that element on the fixture, so it is now the actual dangling-colon signature": </strong>".Byte pins recomputed from the assets, never hand-edited:
next-sessions.js4,557 -> 5,346Both deltas are 789, which is the cross-check that the page pin moved by exactly the part's growth and nothing else changed underneath.
Full pre-PR suite green: ruff,
ruff format --check,mypy --strict(108 files),lint_embedded.py(node present, so the JS syntax check really ran),validate_plugins.py,bump_version.py --current(0.16.0, no manifest in the diff), 1,935 dashboard tests + 192 scripts tests OK, coverage 90.7% against a threshold of 73.