feat(skills): recent-work, a wrap-up that offers to onboard, and a repo-first check-follow-ups - #45
Merged
Merged
Conversation
Two read-side gaps, both in what a session already knows and never says. recent-work — what the daily notes say was achieved. The mirror of check-follow-ups: same notes, same window rule (notes back, not days back), same attribution, same group-never-filter. It reads each note's ## Built bullets and the ## Follow-ups ticks that closed, newest first, this repo in full and every other repo as a count. make recent-work, NOTES=n for a wider window, SINCE=YYYY-MM-DD for a calendar span. A #outcome/dropped or #outcome/handed-off tick is never reported as an achievement — the tick records that nobody did the work, so listing it is the inverse of what it says. superseded is reported and labelled; a bare `- [x]` counts as done, as it always has. A `## Built (<repo>: …)` label now attributes its own section's items. note_context_repo deliberately refuses to answer for a day with two labelled streams — it is a question about the whole note — so every bullet on such a day went to "no repo identified" while the heading two lines above named the repo. update-second-brain now asks onboarding-state.py in Step 1 and, when the repo has never been rendered into, offers in a new Step 5b: shared, quiet (--local), not now, or never for this repo. It picks none of them; shared and quiet differ in who else ends up seeing those files. The question comes after the capture is committed and pushed, never before — a question is a place a session can stop, and a wrap-up that stops before its commit is the failure Step 5 exists to prevent. "Never for this repo" is recorded in a never-ask list beside the repo registry, same format, optional reason, --undecline to reverse it. A separate file because the registry is the set of repos this machine rendered into, and a mode meaning "none" is one render.py is right to refuse. It stops a prompt and never an instruction: onboard-repo does not read it. doctor reports its size on clean runs and uninstall leaves it alone, because a decision nothing mentions is one nobody can undo. unrender-repo points at it too — a retired repo otherwise reads as never-onboarded and gets re-offered at the next wrap-up. lib/followups.py now reads any of a daily note's list sections rather than only ## Follow-ups; registry.py gains rendered() and write_entries(), one atomic writer shared by both lists, and the marker-drift test covers all three copies of the provenance string.
Standing in a repo and asking what is open is one question, and it was taking two: run the check, then ask it to focus on this repo. --brief computed exactly the right shape and was opt-in, so the common case printed thirteen fully-described items from three other repos whenever the flag was forgotten. --recent is now brief by default: this repo's items in full, every other repo as a count. --full is the way to every item; --brief still works and now collapses the long-range audit the same way. The --stale-days audit's default is unchanged, so make audit and a vault's CI print what they always did — that one is a sweep, and it usually runs where there is no repo to be relative to. A repo-scoped run also ends with Next: at most four lines, from what the report already computed. A blocker to clear first, work the repo says already landed and should be confirmed, the oldest item still open here, and how many have been open past three weeks and are worth re-deciding — closing one #outcome/dropped is a real answer, and a list of open items never said so. Each line points at an item by date and never repeats its text. Every item appearing exactly once is what makes this report readable, and a suggestions block that re-lists items breaks it the same way the "blockers first" section did. Nothing is ticked either: the landed line says confirm, because the evidence is about the ref and the item usually says more than the ref does. The block is absent when there is nothing to suggest, when there is no repo, and in the audit — an invented next step is worse than none.
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.
Three read-side gaps, all in something a session already knows and never says.
recent-work— what the daily notes say was achievedThe mirror of
check-follow-ups. That one answers what is still open; this answers what got done, from the same notes, the same window rule (notes back, not days back, so a weekend or a vacation costs nothing), the same attribution and the same group-never-filter discipline.## Builtbullets and the## Follow-upsticks that closed, newest first — there, age is the finding; here, the most recent thing is what a status update leads with.--fullexpands,--reporeports on one you are not standing in, and the total is stated before any grouping.make recent-work,NOTES=nfor a wider window,SINCE=YYYY-MM-DDfor a calendar span (a sprint, a month).#outcome/droppedor#outcome/handed-offtick is never reported here. The tick records that nobody did the work; listing it as an achievement is the inverse of what it says.supersededis reported and labelled, and a bare- [x]counts as done, as it always has.## Builtsection at all — a thin record and a quiet week read identically in a summary and lead to opposite conclusions.A
## Built (<repo>: …)label now attributes its own section's items.note_context_repodeliberately refuses to answer for a day with two labelled streams — it is a question about the whole note — so every bullet on such a day landed in "no repo identified" while the heading two lines above it named the repo.check-follow-upsis repo-first by default, and says what to do nextStanding in a repo and asking what is open is one question, and it was taking two: run the check, then ask it to focus on this repo.
--briefcomputed exactly the right shape and was opt-in, so the common case printed thirteen fully-described items from three other repos whenever the flag was forgotten.--recentis now brief by default.--fulllists every repo's items;--briefstill works and now collapses the long-range audit too; the two together are refused rather than resolved.--stale-daysaudit is unchanged, somake auditand a vault's CI print exactly what they did. That one is a sweep, and it usually runs where there is no repo to be relative to.#outcome/droppedis a real answer).Each Next line points at an item by date, never by repeating its text. Every item appearing exactly once is what makes this report readable, and a suggestions block that re-lists items breaks it the same way the "blockers first" section did. Nothing is ticked: the landed line says confirm, because the evidence is about the ref and the item usually says more than the ref does. The block is absent when there is nothing to suggest, when there is no repo, and in the audit — an invented next step is worse than none.
A wrap-up in a repo that was never onboarded says so, once
update-second-brainasksonboarding-state.pyin Step 1 and, when the answer isnot-onboarded, offers in a new Step 5b: shared, quiet (--local, so the repo's remote never sees the rules), not now, or never for this repo. It picks none of them — shared and quiet differ in who else ends up seeing those files.The question comes after the capture is committed and pushed, never before. A question is a place a session can stop, and a wrap-up that stops before its commit is the exact failure Step 5 exists to prevent.
"Never for this repo" is recorded in
${XDG_CONFIG_HOME:-~/.config}/second-brain-workflow/onboard-declined— same format as the repo registry beside it, optional reason,--undeclineto reverse. A separate file rather than a registry field: the registry is the set of repos this machine rendered into, and amodevalue meaning "none" is onerender.pyis right to refuse. It stops a prompt and never an instruction —onboard-repodoes not read it, so "onboard this repo" always wins.make doctorreports the list's size on a clean run andmake uninstallleaves it alone, because a decision nothing ever mentions is one nobody can undo.unrender-repopoints at it too: a retired repo otherwise reads as never-onboarded and gets re-offered at the next wrap-up.Supporting changes
lib/followups.pyreads any of a daily note's list sections, not only## Follow-ups—section_items,labelled_sections,heading_repo;collect_spanstakes an optional heading and is otherwise unchanged. One parser, so the two sides cannot disagree about what an item is.registry.pygainsrendered()(the Python mirror ofsbw_registry_marker_present) andwrite_entries(), one atomic writer shared by the registry and the never-ask list.tests/test-repo-registry.shnow asserts all three copies of the provenance marker are the same string.Testing
make checkgreen. 79 new assertions —tests/test-onboarding-state.sh(36),tests/test-recent-work.sh(28), 15 intest-check-followups.sh, plustest-doctor.shandtest-repo-registry.sh— and a fixture vault of its own so no existing count shifts. Two existing tests now pass--full, since they assert on items in other repos and the window collapses those by default.After merging,
make sync-skillsinstallsrecent-work; it stays invisible until an agent restart.🤖 Generated with Claude Code