Commits
100 commits · main · older page 4
Max Rakhimov · 2026-09-13 · 44737f032138
The page put an h1 and a p.meta where the app put a div.subject and a
div.detail-meta, and neither had a chip slot: a head chip landed before
the page's meta bits and after the app's commit hash.
Max Rakhimov · 2026-09-13 · 97ece10cfe66
CreateFeedback now refuses a suggestion whose body carries no suggestion
fence, so the showcase fixture's --suggest call failed and the whole
browser battery stopped at the fixture build.
Max Rakhimov · 2026-09-13 · 33635609618e
One code on the suggestion path had no test: WRITE_ERROR. The CLI, the
RPC server and the skill branch on these strings, so a rename or a
reordered guard changed the contract without failing a test.
Max Rakhimov · 2026-09-13 · 7189cc521cff
Two codes on the post and list write paths had no test: COMMIT_ERROR and
GIT_ERROR. Both need git itself to fail, so no test reached them. The CLI,
the RPC server and the skill branch on these strings, so a rename or a
reordered guard changed the contract without failing a test.
Max Rakhimov · 2026-09-13 · 7683852b31b6
Three codes on the issue and milestone write paths had no test: RETRACTED,
DUPLICATE and LINKS_FAILED. The CLI, the RPC server and the skill branch
on these strings, so a rename or a reordered guard changed the contract
without failing a test.
Max Rakhimov · 2026-09-13 · 88aba08d357c
Nine codes on the artifact, push and SBOM paths had no test: READ_FAILED,
LFS_UNAVAILABLE, WRITE_FAILED, DUPLICATE, NO_SBOM, NO_VERSION,
SBOM_FAILED, UPLOAD_FAILED and RECORD_EDIT_FAILED. The CLI, the RPC
server and the skill branch on these strings, so a rename or a reordered
Max Rakhimov · 2026-09-13 · fbbbc5da2bf8
Six codes on the accept and decline paths had no test: LOOKUP_FAILED,
NOT_A_PROPOSAL, CANONICAL_RETRACTED, NO_DELTA, UNSUPPORTED_TYPE and
DECLINE_FAILED. The CLI, the RPC server and the skill branch on these
strings, so a rename or a reordered guard changed the contract without
Max Rakhimov · 2026-09-13 · 95a09b0c9e96
The memo error-code tests carried a local skipWithoutFilesRefBackend. The
proposals and release error-code tests on this branch need the same skip,
so the one copy becomes three unless it moves.
Max Rakhimov · 2026-09-13 · 626200918ad7
Eleven exported symbols had no reference outside the package: the branch
observation type and its reader, the dependents query, the item query and
its struct, the batch insert, the feedback item type constant, the workspace
batch processor, the open-branch refresh, the branch
Max Rakhimov · 2026-09-13 · 2c6796e1fa18
REVIEW.md said every feedback is marked stale when the code changed; only a
verdict is, and an inline comment keeps the commit and lines it was written
against, which the branch leaves as it is (spec 1.7 anchors are a later
item). The branch-sync line now says pr sync works on a
Max Rakhimov · 2026-09-13 · 00766167111e
Every comment in the package is one line, saying what the code does. The
em-dashes are gone, the file headers of observe.go and
provider_branches.go are one line each, and schema.go's init keeps one
line for the migration a reader has to understand.
Max Rakhimov · 2026-09-13 · f3338c147b14
ApplySuggestion raised invalid, parse_error, file_error, range_error and
write_error where every other code in the tree is upper snake, and no
test asserted any of them. They become NOT_SUGGESTION, PARSE_ERROR,
FILE_ERROR, RANGE_ERROR and WRITE_ERROR, each asserted by the
Max Rakhimov · 2026-09-13 · a38493c38bbf
Reviewer, Offset, SortField, SortOrder and PRRef on ReviewQuery were set
by no production caller; SortField and PRRef were never read at all, and
the order outside a test was always timestamp DESC.
Max Rakhimov · 2026-09-13 · dab849f43f01
Nine small pairs and four delegates said the same thing twice.
Max Rakhimov · 2026-09-13 · 9fa33a124ab1
The latest-verdict-per-author fold and the approved and
changes-requested counters were written three times, in
ComputeReviewSummary, GetBatchReviewSummaries and
GetVersionAwareReviews, so GITREVIEW.md 1.8's rule lived in three
shapes.
Max Rakhimov · 2026-09-13 · d46ff3227082
countUnreadFeedback and countUnreadPRStateChanges restated their
getters' predicates as COUNT queries, so each predicate lived in two
places while three other counters already took len of their getter with
unreadOnly. They now do the same.
Max Rakhimov · 2026-09-13 · 9f12c5a45181
InsertReviewItem and InsertReviewItems carried the same 24-column
INSERT and the same linking-table rebuild, so a new column had to be
added twice. The single insert now calls the batch.
Max Rakhimov · 2026-09-13 · 33d31324dd79
The require-review key was read into ReviewConfig and used by nothing,
so `review config set require-review true` changed no behavior.
GITREVIEW.md 1.8 lets an implementation add merge requirements, and
MergePR now refuses with REVIEW_REQUIRED while the summary is not
approved.
Max Rakhimov · 2026-09-13 · 958ac2a7e42c
getBranchStateNotifications listed pull requests on a hardcoded
gitmsg/review, so head-advanced and the other three branch
notifications went silent for a repository configured with another
branch. The provider has a workdir, so it resolves the branch.
Max Rakhimov · 2026-09-13 · 09554d9ab254
A bare hash was resolved by guessing its branch: GetReviewItemByRef
defaulted to gitmsg/review, so `pr show <hash>` read NOT_FOUND for a
repository configured with any other branch. GetPR and GetFeedback then
scanned the newest 1,000 items, missing an older one and matching on a
Max Rakhimov · 2026-09-13 · 66fde6b7b0b1
retargetDependents discarded UpdatePR's result and logged the retarget
as done, so a dependent left naming the merged head looked retargeted in
the log. It now returns one error per failed edit and MergePR logs each
at Warn with its code; the merge itself has already landed, so
Max Rakhimov · 2026-09-13 · 5e90da1e6a24
ParseSuggestionCode took the first fence of any language, so feedback
that quotes the current code in a go fence before its suggestion fence
wrote the current code back over the file. GITREVIEW.md 1.4 makes the
suggestion fence a MUST, and the pattern now matches only that.
Max Rakhimov · 2026-09-13 · 1b70f25a3942
CountPullRequests counted every repository in the cache while
GetPullRequests filters by repo_url, so the TUI list total and the CLI
status line both read high once any followed repository had a pull
request. It now takes the repository, and its three callers pass the
workspace.
Max Rakhimov · 2026-09-13 · 3ce9c9db427c
getDraftReadyNotifications matched a message line "Draft: true", a shape
the writer never emits: it puts draft="true" inside the GitMsg: line, so
pr-ready never fired. NOTIFICATIONS.md documented a type nothing raised.
Max Rakhimov · 2026-09-13 · c8bb864f3332
MergePR read a relative head as a workspace branch, so a fork pull
request written as --base '#branch:main' --head 'feature', the form the
fork-discovery flow shows, merged the upstream's own branch of that name
or failed with HEAD_NOT_FOUND. One headSource(existing, pr) now
Max Rakhimov · 2026-09-13 · 2cbfd0b69742
prFieldOrder omitted adopts, so the writer left it to the alphabetical
remainder while the spec said nothing. The field now has a declared
position and the emitted header matches GITREVIEW.md 1.2.
Max Rakhimov · 2026-09-13 · 4498fb594c6c
GITREVIEW.md named adopts in 1.5 only. The writer emits adopts and
accepts on pull requests, so 1.2's field order, the manifest and the
validation table now carry them and a reader can reconstruct the header.
Max Rakhimov · 2026-09-13 · aefaf82bd0d0
Removing a repository leaves the comments it wrote counted on posts that
stay: DeleteRepository takes its rows, and nothing recounted the targets
those rows named. It also deleted from social_counted_sources, which the
social migration drops, so on a migrated cache the whole
Max Rakhimov · 2026-09-13 · c77677a543e6
SOCIAL.md said nothing about interaction counts or the activity log, the two
places this branch changed what a reader sees. The architecture row named
GetTimeline as a key export, which no caller outside the package reaches;
the API is GetPosts with a scope, and CreateComment
Max Rakhimov · 2026-09-13 · 41596acb05fc
Every em-dash in the package goes, 27 across the tree, and each rationale
block becomes the one line the next editor needs: what a query drives from,
what a ref field carries, which spec rule a check enforces. scanResolvedRow
carried two stacked comments, one describing a
Max Rakhimov · 2026-09-13 · 6e32fdd77faa
social_notification_reads was copied into core_notification_reads on every
cache open, though nothing had written it since the core table took over, and
social_counted_sources was the gate the recount replaced. Both CREATE
statements leave the schema and one
Max Rakhimov · 2026-09-13 · 754531cdf089
GetRelatedRepositories sorted by score alone with sort.Slice, so two
repositories with the same score came back in whatever order the map walk
produced and `social related` printed a different list each run. The rest of
the command's limits, the 1,000-item window and the
Max Rakhimov · 2026-09-13 · 68e4650e59b4
GITSOCIAL.md 1.2 gives a repost two subject forms, the local one for a post
in this repository and "# <Author> @ <owner>/<repo>: <excerpt>" for a remote
one; the writer always wrote the remote form, so a repost of your own post
read "# Alice @ alice/repo: ..." instead of "#
Max Rakhimov · 2026-09-13 · 20f15f9a39d1
processWorkspaceCommits had no caller: ProcessWorkspaceBatch is the workspace
sync path, and the six tests that pinned the old function now drive it.
fetchSocialListRefs was a no-op still registered as a fetch hook, since
storage.FetchRepository fetches every refs/gitmsg/* ref
Max Rakhimov · 2026-09-13 · dac8106535db
sortNotificationsByTime was an insertion sort, appendUnique and uniqueURLs
were slices.Contains, and formatDate and FormatRelativeTime were two
relative-time formatters with two vocabularies. relativeTime keeps both: the
short form for the column-aligned CLI log line, the long
Max Rakhimov · 2026-09-13 · fd2ba594dce4
parseRefField and parseSocialRefField were the same parse, extractPostType
was GetPostType without the ext check that both call sites had already made,
and the social_items upsert stood in three places. buildSocialItem now
serves the fetch path as well, and socialItemUpsert with
Max Rakhimov · 2026-09-13 · 79b037db4253
GetNotifications, GetUnreadCount, MarkAllAsRead and MarkAllAsUnread each
carried the same seven-argument predicate inline, so a change to what raises
a notification had to land in four places. It is one const beside
userThreadsCTE, with its aliases and parameter order on it.
Max Rakhimov · 2026-09-13 · bc4e06b3c70d
CreatePost, createInteraction, EditPost and RetractPost each repeated the
same seven steps: commit on the branch, read the commit back for its author,
ask git for the unpushed set, build the Post, insert the commit row and
insert the social item. commitSocialMessage and
Max Rakhimov · 2026-09-13 · b6190b6ad8f8
GetSocialItems and buildAllItemsWhere built the same WHERE twice, and the
two list clauses had already drifted apart: one matched repo_url, the other
(repo_url, branch), which matches no post, since posts live on gitmsg/social
while a list entry names the code branch. Six
Max Rakhimov · 2026-09-13 · 9e08b21a7076
A list scope bound the empty workspace into the follower join, because
GetTimeline used one argument for the list filter and for the FollowsYou
mark, and a list scope leaves workspace posts out by passing "". A post from
a repository that follows the workspace therefore carried
Max Rakhimov · 2026-09-13 · fff3f778b066
A retraction never lowered a count: the retraction is written as an edit,
the insert skipped edits, and no path subtracted, so a thread whose only
comment was retracted still read "1 comment" on the card. The two increment
walks, the social_counted_sources gate and the missing
Max Rakhimov · 2026-09-13 · 2b60827ff1f2
detectLogEntryType read the type of the item a commit references, so a
comment on a post logged as a post, and it matched ref shapes git.ListRefs
never returns, so every list and config commit logged as a metadata update.
It now reads the item's own type through GetPostType and
Max Rakhimov · 2026-09-13 · 2807d8879176
notifications no longer imports fetch, so it sits beside settings, above
storage, gitmsg and identity. gitmsg/divergence is gone from the stack; its
provider lives in notifications.
Max Rakhimov · 2026-09-13 · 1026eb3efe65
The notification now reaches every client. No TUI card renderer claimed
gitmsg-divergence, so the list showed "Unknown Item", and the CLI printed a
bare header with no branch. Both now name the branch and say it diverged
from origin, in the same words. The note decided the three
Max Rakhimov · 2026-09-13 · bd2740021fb4
The provider sat in core/gitmsg/divergence to dodge an import cycle that
the dropped fetch edge removed, and only the CLI's blank import reached it,
so the diverged-branch notification never fired in the TUI or over RPC.
It now registers from the notifications init like the
Max Rakhimov · 2026-09-13 · 634f772a68e4
MentionProcessor and TrailerProcessor named fetch.CommitProcessor as their
return type, the only reason notifications imported fetch. That edge put
notifications above fetch in the core stack, so a provider needing gitmsg
could not live there. The unnamed func type is assignable
Max Rakhimov · 2026-09-13 · a0059d7c4d39
Two comments on the release head tests ran two and three lines; the rule is one line per comment. Missed in the branch review and fixed on main as its own commit, per the review-fix rule.
Max Rakhimov · 2026-09-13 · 3a6651050bf0
A release's list rows and item pages changed markup: the head takes the tag
as its subject, the version rides a trailing chip, and the tag left the meta
line. Published pages carry the old shape, so every one has to regenerate.
Max Rakhimov · 2026-09-13 · c2e9d2233818
The lists view wrapped its subject and its extension chip in an unclassed
div, so the one row on the site that is a card did not carry .card-head:
the chip trailed the subject instead of leading it, and a literal space
stood in for the head's own flex gap.
Max Rakhimov · 2026-09-13 · 291295533a17
A release rendered its version twice. The app's card took the tag as its
subject and then repeated it on a "v<version>" chip; the page's item head
put the first line in the h1 and the same string in a "tag <tag>" meta bit.
Max Rakhimov · 2026-09-13 · ae67f01221d9
The golden loop only compared text, so a panel drawn past the terminal
edge showed up as a golden diff and nothing named the cause. Each of the
seven golden routes now checks the frame it just rendered: no line wider
than 120 columns by AnsiWidth, and 40 lines.
Max Rakhimov · 2026-09-13 · daa44a372b5c
The last parser in the M7 sweep with no fuzz target. The target seeds the
inline forms CLI.md documents plus the edge shapes, and asserts the parts
re-join to the same filters and free text, that a value is the run the
query spells after its prefix, and that ftsQuery balances
Max Rakhimov · 2026-09-12 · 67b155bc2ef2
An item page's feedback replies changed markup: the card takes the feedback
variant and its verdict class, and the anchor moved from the meta line to a
chip. Published pages carry the old shape, so every one has to regenerate.
Max Rakhimov · 2026-09-12 · 67e61258a028
Ten fb-* classes styled a component that is a card: its own border, radius,
padding and margin, a head row, an icon and an author span. The card rules
carry all of that, so the sheet keeps only what deviates, the verdict on the
left border, and the diff containers carry the
Max Rakhimov · 2026-09-12 · b5cd8bf8db78
The app hand-rolled the feedback card: its own container, head, icon and
author spans, none of which the page layer emitted. It now goes through
card(), so the verdict rides the variant and a chip, the file and line
anchor is a chip, and the author and time sit in the meta row
Max Rakhimov · 2026-09-12 · ef8e1a6867c3
A feedback reply shipped its own chip vocabulary: a reviewer-chip class the
page never used as a reviewer chip, and the file:line anchor as plain meta
text. It now leads with the card variant classes the app will build from the
same names, a verdict chip and an anchor chip.
Max Rakhimov · 2026-09-12 · 74cb540be3ad
Eighty-eight package-level declarations in the audited files were exported
with no reference outside tuicore: the muted identity styles and colors the
title and badge helpers read, the markdown pipeline steps, the footer
builders behind the four footer entry points, the
Max Rakhimov · 2026-09-12 · 3303b543d4d7
The prefix table calls util_ stateless helpers, and five util_ files held
stateful types: CardList, SectionList, Pagination and AnchorCollector are
components, and the keybinding registry is a registry. They take those
prefixes now, and the table's util_ row reads "helpers and
Max Rakhimov · 2026-09-12 · ad0fea347066
Six comments named something the code does not do. CardOptions.MaxLines
said 0 was unlimited, where 0 is the default of five and -1 is unlimited.
util_diff.go and util_keys.go pointed at HIGHLIGHT-DESIGN.md,
DIFF-DESIGN.md and KEYS.md, none of which exist. The four exported
Max Rakhimov · 2026-09-12 · 39f81c074191
Twenty-one declarations had no reference anywhere in the tree, so they read
as available API while nothing depended on them: the AccentHyperlink and
AccentImage colors (the string constants beside them are what the ANSI
sites use), ContentPaddingBottom, the Doc and Normal
Max Rakhimov · 2026-09-12 · b0bed6b7d7b7
RenderProgressBar re-tested total against zero twice after returning for it,
which read as if a zero could still arrive; the early return covers every
non-positive total instead. The two loop-variable captures in
RegisterGlobalKeys date from before per-iteration loop variables.
Max Rakhimov · 2026-09-12 · 80052c5fbf28
FormatTime's date fallback formatted in the value's own zone while
FormatFullTime converts to local, so a late-evening commit from another
zone read as one day in a list and the next day in its detail view.
FormatOriginTime feeds RFC 3339 zones straight in and inherits the fix.
Max Rakhimov · 2026-09-12 · 8a9a331cfff7
Eleven package-level values followed the terminal background or cached what
it renders: the background flag, two glamour renderers, two chroma styles,
the focused-link marker, and the glamour, line, code and search caches.
They were written from three files and refreshed by a
Max Rakhimov · 2026-09-12 · 2e97844f3480
Five extension keys hold places for extensions that do not exist: C, O, Y,
| and F. The entries stay, since the reservation is what keeps a new
extension from taking a key another one will want, and one line above them
says so. Their five domain constants had no other reader and
Max Rakhimov · 2026-09-12 · bb00c1f48255
CardOptions.Bold had one writer, the thread anchor, and it only ever set it
beside Markdown, where the bold glamour renderer carried the same styles as
the plain one: the anchor post was not bold on screen. Glamour cannot style
the body, so the bold is applied per rendered line
Max Rakhimov · 2026-09-12 · 2d341e748534
Six shapes were written twice or more, so a fix to one missed the others.
Max Rakhimov · 2026-09-12 · d2ff902b8c9f
SetSelected and SelectByID left viewDirty false, so the next View returned
the cached frame with the old cursor. The memo list's SetSourceCursor is
the one caller that reaches it with no other route to a redraw: walking
left and right in a memo detail view left the list cursor
Max Rakhimov · 2026-09-12 · 15aa726acefd
TruncateToWidth cut at a rune index, so it could land inside a color
sequence and always dropped the trailing reset, leaving the rest of the
line painted. It walks forward now, skipping escapes whole, stopping at the
width, and closing a style the cut left open. The walk also
Max Rakhimov · 2026-09-12 · fda01dca91ec
The icon was stripped from the title only, so an editor name, a subtitle
part, a badge or a nested card's title carrying the key glyph rendered a
badge the author had not earned. Each user-controlled header field in
renderHeader and renderNestedCard is stripped now, and the
Max Rakhimov · 2026-09-12 · aace9cc37f29
CardHeight counted raw newlines, ignoring the wrap width, the markdown
render and the MaxLines mapping, so a long paragraph or an unlimited body
scrolled the selected card out of the frame. CardList now measures a card
by the line count of its rendered string, filled lazily from
Max Rakhimov · 2026-09-12 · 229c7b537041
Label grouping read a field filled only for issues and pull requests,
so `search --group-by label` put every release, post, comment and memo
under (none) however many labels they carried.
Max Rakhimov · 2026-09-12 · c9f49a54911e
Grouping by state, assignee, reviewer or base ran a second query over
pm_items and review_items for columns the search row already carried,
and grouping by milestone ran one query per distinct milestone to turn a
composite ref into a name.
Max Rakhimov · 2026-09-12 · e2e9fc780f28
groupBy ordered groups with sort.Slice on count alone, so two groups of
the same size came back in whatever order the map iteration produced.
The same search printed its groups in a different order on each run.
Max Rakhimov · 2026-09-12 · 05c799dfaba5
group_test.go tested the enrichment round trip rather than the grouping
a user asks for, so it pinned three defects: equal-count groups in map
order, a second query for fields the search row already carries, and
labels that only reach issues and pull requests.
Max Rakhimov · 2026-09-12 · acfd9aa737ac
Five codes on the stack and version paths had no test: NOT_A_STACK,
REBASE_FAILED, RESOLVE_FAILED, MISSING_TIPS and TIPS_UNAVAILABLE.
INVALID_TARGET was asserted only for a social post. The merge and close
guards that refuse a pull request aimed at another repository had no test
Max Rakhimov · 2026-09-12 · b502fe375a10
Five codes on the session and tier sync paths had no test:
SESSION_DIR_FAILED, PERSONAL_DIR_FAILED, GC_FAILED, CACHE_CLEANUP_FAILED
and PUSH_FAILED. The CLI, the RPC server and the skill branch on these
strings, so a rename or a reordered guard changed the contract without
Max Rakhimov · 2026-09-12 · 05e2dafd15ea
The docs say a push sends refs and objects, and a push to an s3 remote
with site.publish then rebuilds the site. The help called both steps
publishing, so --no-site and --site-only read as data flags.
Max Rakhimov · 2026-09-12 · da78d6e03e6a
Eight codes on the memo write paths had no test: INVALID_LABELS,
READONLY_TIER, TIER_INIT_FAILED, PROJECT_INIT_FAILED, PERSONAL_INIT_FAILED,
SESSION_INIT_FAILED, REF_WRITE_FAILED and REF_DELETE_FAILED. The CLI, the
RPC server and the skill branch on these strings, so a rename or
Max Rakhimov · 2026-09-12 · a5261767e02a
Ten codes on the PR merge path had no test: DRAFT_PR, UNMET_DEPENDENCY,
MERGE_INCOMPLETE, BASE_NOT_FOUND, MERGE_FAILED, NOT_DRAFT, ALREADY_DRAFT,
BASE_UNRESOLVED, INVALID_REFS and SYNC_FAILED. The CLI, the RPC server and
the skill branch on these strings, so a rename or a
Max Rakhimov · 2026-09-12 · 9d465bac73fc
The single go build was already shared through a sync.Once, but neither
temp directory was removed at exit: 229 leaked pairs and 4.3 GB here.
The harness moves next to TestMain, which removes the shared root after
m.Run. The binary sits in bin/, so the helper tests can still put
Max Rakhimov · 2026-09-12 · 8e94b9ceb475
FetchSocial was the one adapter fetch path with no test, so a change to
the discussions query or its decoding failed only at import time against
a live repository. The new tests drive it through the gh exec seam the
other fetch tests use: decoding, filters, empty, error, and
Max Rakhimov · 2026-09-12 · d796fdae36c4
Fixes from a branch review have been folded into the commit they correct since the objstore-lean branch, so each commit on main is its reviewed shape and bisect lands on coherent commits. A fix for a defect that was already on main is a change to main and keeps its own subject
Max Rakhimov · 2026-09-12 · b21194071eb4
"push" named two things in CLI.md, S3.md and STATIC-SITE.md: sending refs
to a remote and rebuilding the static site an s3 remote serves. A reader
could not tell which a sentence meant. Push now names the refs alone, and
"rebuild" names the pages and indexes a push to an s3
Max Rakhimov · 2026-09-12 · 223f388a5a18
Every s3 remote URL the CLI stores passes through ParseS3URL, and a
misread bucket or endpoint host signs requests at the wrong place. The
target asserts the parts round trip through the canonical form callers
write, and that protocol.NormalizeURL folds the same input the same
Max Rakhimov · 2026-09-12 · 0e5f8525a707
Five places the docs said something the code does not do.
Max Rakhimov · 2026-09-12 · 323e2c176d7f
writePackState had one caller, a test that owns the whole document, so it
is gone and the test writes the two lines itself.
Max Rakhimov · 2026-09-12 · b6f362da0773
With upstream unreachable, a thin push excluded against the pins the
bucket records, checking only that their objects sit in the local odb.
That proves nothing about upstream still serving them, so a reader's
overlay could be left unable to resolve an object upstream had
Max Rakhimov · 2026-09-12 · ef1addbc4f36
Five copies, each doing the same work twice.
Max Rakhimov · 2026-09-12 · 61d482261927
looseUploaded was credited in uploadDelta before filterPresentObjects
dropped what the bucket already held, uploadPacked's oversize fallback
added the same delta a second time, and nothing reset it between push
batches. LooseSinceSeal inflated, so sealDue fired early and each
Max Rakhimov · 2026-09-12 · c94651f12a44
Five loops spawned one git process per ref: uploadMissingObjects ran
rev-parse then cat-file -t per src, applyRefUpdate ran the same rev-parse
again, and remoteTipsPresentLocally, bucketRefTips and
missingBucketObjects each ran cat-file -e per ref. On a push of 100 state
refs
Max Rakhimov · 2026-09-12 · 29427cb72c6e
canonicalURIEncode returned its input while its comment described
per-segment encoding. Go's EscapedPath leaves !$&'()*+,;=:@ unescaped in
a path and AWS's UriEncode escapes them, so any key carrying +, @, = or ,
signed wrong and the provider answered 403. An artifact version
Max Rakhimov · 2026-09-12 · 450de79c3608
The retry was a property of the caller, not of the request. Twelve read
sites and every write site called do bare, so one 503 on an object
download failed a whole clone, while five nested loops composed to nine
attempts and about 9.5 s per object on a dead endpoint.
Max Rakhimov · 2026-09-12 · d0cd6bd07027
ExecLocked and QueryLocked hold no process mutex: concurrency rests on the
WAL journal and the database/sql pool, and no test drove them from more
than one goroutine. Four writers and four readers now share one temporary
cache, so -race has a shared-state path to inspect and the
Max Rakhimov · 2026-09-12 · db9c545eac47
Ten of the thirteen functions in lfs.go had no test: the local object
store, the unpushed count, the push over gitmsg refs, the Batch API
download and the credential lookup. The object store round-trips through
a real repository, the push paths run against the executor hook, and
Max Rakhimov · 2026-09-12 · 2e023bf90519
ParseHeader, ParseMessage, ParseRef and ParseLFSPointer read untrusted
commit messages and file content, and only ParseSBOM was fuzzed. Each
target seeds from the forms in GITMSG.md and the LFS v1 spec, and asserts
the parser against the writer that feeds it: an accepted input
Max Rakhimov · 2026-09-12 · 810c80033c0a
tuicore becomes infrastructure only: utils, components, registries and the
message bus. Its non-test line count drops from 14,575 to 10,045, with the
thirteen routable views (4,546 lines) now in tuiviews. HistoryView stays in
tuicore as component_history.go, since the extension
Max Rakhimov · 2026-09-12 · ac83792b00dd
Every site_* file, the embedded assets and the browser battery move to
library/core/site, which imports objstore for the S3 transport; nothing
in core imports it back. The assets land under site/assets so the embed
stays inside the embedding package, and the scripts, the docs
Max Rakhimov · 2026-09-12 · 93bbcf485d19
RunHelper takes a PostPushHook, and the CLI passes the site's pass as
that hook, so the transport half of postPushMaintenance no longer knows
what a gitmsg branch or a site artifact is. PushOutcome carries the
client, prefix, GIT_DIR, refs, updates, default branch, override,
Max Rakhimov · 2026-09-12 · 2c9b01010c96
The static site is about to leave this package, so every transport symbol
it calls becomes an exported one: the local commit source, the brotli and
compressed-document helpers, the ref and pack-map readers, the upload pool
and the cache class. The in-memory bucket stub moves to
Max Rakhimov · 2026-09-12 · f93d0be1c8ae
TestSmoke pressed every key of a view's context on every view: 1,676
subtests in 94 s. Each view now gets the keys its own context binds plus
one unbound key, and each global shortcut runs once on the first view
that binds it: 86 subtests in 38 s. The harness also skips tea.Tick