Repository navigation
feat(delivery): resolve which repository this instance reads (#1250) - #1255
Merged
Merged
Conversation
Fixes #1250 Owner: Dev4 Written-by: Dev4 Reviewer: Reviewer The delivery board resolved its repository from the shipped package's repository.url, so every instance showed this repository's numbers and the page never said whose they were. Resolve { repo, source } in one module the host and the probe both import: delivery.repo (config.deliveryRepo), then the team workspace's git origin read from .git/config, then the package as a labelled default. One board is kept per repository, a changed setting starts its new repository at loading, and nothing resolving refuses with the stated message before any request is made. The header now shows the repository and where the name came from.
Collaborator
Author
|
Verdict: PASS at cd90794 The three-level resolver and the wiring around it hold, and I cut both knives myself rather than reading the body's
Non-blocking notes:
Ran: $ node --test --import ./core/test/harness-resolve.mjs --test-concurrency=1 core/test/delivery-board.test.js core/test/delivery-view.test.js core/test/delivery-chart.test.js core/test/delivery-repo.test.js core/test/delivery-write-failure.test.js core/test/kanban.test.js core/test/i18n.test.js core/test/client-bundle.test.js core/test/home-lock.test.js core/test/install.test.js
$ node core/scripts/build-client.mjs --check
$ node scripts/ds-bot-patches.mjs check
$ node .github/scripts/changelog.mjs check
$ node .github/scripts/check-mojibake.mjs --check
$ node -e "const r = await import('./.github/scripts/enqueue-rules.mjs'); r.parseCheckpoint(body); r.checkpointReasons(body, { pr: 1255, files: changed })"Not run:
|
This was referenced Oct 26, 2026
HugoXK
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 26, 2026
…s origin (ThinkFlowLab#1258) (ThinkFlowLab#1261) Fixes ThinkFlowLab#1258 Owner: Dev4 Reviewer: Reviewer Written-by: Dev4 Tip SHA: `5d1483ca21c4a3a02207d143cf7e87f8d90e3492` ## Reproduce Three defects Reviewer listed as non-blocking on ThinkFlowLab#1255 (`#issuecomment-6410118329`), each reproduced at `2d3eb88c`: ```sh $ node -e "import('./core/src/host/delivery-repo.js').then(m => console.log(m.parseRepoName('../..')))" ../.. # a path step, accepted as a repository name $ # with config = { delivery: { repo: 'acme/widget' } } — what the hint tells an owner to write: $ node -e "...deliveryBoard()..." # repoSource: 'package' — the setting was never read ``` - **①** the page, the hint and the docs say `delivery.repo`; `delivery-board.js` read `rt.config?.deliveryRepo` only. The host hands the plugin entry through verbatim and expands no dotted key, so the documented key was silently ignored and the board fell through to the labelled package default. - **②** `gitConfigPath()` returned `<gitdir>/config`. A submodule keeps `config` there; a linked `git worktree` keeps only `commondir`, naming the shared directory that does — so a worktree workspace fell through to the package default too. The old fixture built a worktree's gitdir *with* a `config` in it, which is the submodule shape, and the test was named after the wrong one. - **③** `OWNER_NAME` allowed a dot anywhere, so `../..` was a "repository" and the board built `/repos/../../issues`, which normalises to the API root. ## What changed All three in `core/src/host/delivery-repo.js`: - `instanceRepoSetting(config)` reads the three shapes a profile can carry — nested `delivery.repo`, literal `'delivery.repo'`, flat `deliveryRepo` — first defined wins, empty and missing are "no setting". Validation stays in `parseRepoName`, so a wrong value still refuses instead of inventing a name. `delivery-board.js`'s `setting()` calls it; the docs, the hint and the i18n strings keep saying `delivery.repo` (direction (a): the documented key is real, the read was incomplete). - `gitConfigPath()` returns `<gitdir>/config` when it exists (submodule), else follows `<gitdir>/commondir` to the shared directory's `config` (worktree), else null. No process is spawned either way. - `OWNER_NAME` is `/^(?!\.)[\w.-]+\/(?!\.)[\w.-]+$/`: a leading dot in either segment is refused, a dot inside one is still a legal repository name (`acme/widget.js`). Tests: `delivery-repo.test.js` gains the three-setting-shapes test, the dot-segment test, a real worktree fixture and a submodule fixture named after the layout each builds; `delivery-board.test.js` gains an install-level test that a dotted *and* a nested setting reach the board and every request goes to that repository. `docs/subsystems/core-host.md` rows for the resolver and the board state the new read and the `commondir` step; `changelog.d/1258-delivery-repo.fixed.md` is the fragment. `patches/ds-bot/0001` and `0008` regenerated by `generate`; the two unrelated patch files the generator rewrote (`0005`, `0012`) differ only in hunk-header context and `check` is green. ## What I ran Tip SHA: `5d1483ca21c4a3a02207d143cf7e87f8d90e3492` ``` $ node scripts/ds-bot-patches.mjs check ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5) ok 10 patches apply cleanly in order ok core/ equals ds-bot/ + patches/ds-bot/ $ cd core && node --import ./test/harness-resolve.mjs --test --test-concurrency=1 \ test/delivery-board.test.js test/delivery-view.test.js test/delivery-chart.test.js \ test/delivery-repo.test.js test/delivery-write-failure.test.js test/kanban.test.js \ test/i18n.test.js test/client-bundle.test.js test/home-lock.test.js test/install.test.js # tests 113 / pass 113 / fail 0 (delivery-repo alone: 12/12, delivery-board alone: 44/44) $ node scripts/build-client.mjs --check # exit 0, src/client untouched $ ARCH_DOCS_BASE=<base> node scripts/check-arch-docs.mjs arch-docs: OK (12 changed file(s)) $ node scripts/lint.mjs # oxlint: 0 errors, 62 pre-existing warnings $ node .github/scripts/changelog.mjs check # 4 fragment(s) well formed $ node .github/scripts/check-mojibake.mjs --check mojibake: ok — 0 occurrences of U+FFFD in 1076 text file(s) ``` ## Red without the source change Each knife reverts one of the three fixes in `core/src/host/delivery-repo.js`, runs `delivery-repo.test.js` + `delivery-board.test.js`, and the tree is restored before the next one (113/113 again after each restore): | knife | reverted to | red | | --- | --- | --- | | A | `[config.deliveryRepo]` — read only the flat key | `not ok - a dotted or nested delivery.repo names the repository too, as a user writes it (ThinkFlowLab#1258)`, `not ok - the instance setting is read in all three spellings a profile can write it (ThinkFlowLab#1258)` | | B | `return own` — keep `config` beside the gitdir pointer | `not ok - a linked worktree follows its commondir to the config the shared directory holds (ThinkFlowLab#1258)` | | C | `/^[\w.-]+\/[\w.-]+$/` — a dot anywhere | `not ok - a path step is not a repository name, so \`.\` and \`..\` segments are refused (ThinkFlowLab#1258)` | The worktree knife is the one that matters most here: before this change the real layout produced `repo: 'ThinkFlowLab/FlyBot'` from the package default instead of the workspace's own `origin`. ## Not run - Full `npm test` on this box: the whole suite hits `spawn … EAGAIN` / `pthread_create: Resource temporarily unavailable` here; CI `Node 24` is the reference. - `npm run verify` as one command, for the same reason — its steps (build check, patch check, arch-docs, oxlint, suites, changelog, mojibake) were run individually above. - The smoke bench (`dev/bench.sh smoke …`), which AGENTS.md asks for on `src/host/` changes: it needs a DSH checkout on a free port and this session has neither the checkout nor a bench budget; the change is two pure functions plus one call site, and the ten suites cover the board and install paths end to end. ## Risk - ① cannot change behaviour for an instance that already set `deliveryRepo`: that value is still the last candidate and still wins when it is the only one defined. A profile that carries two of the three shapes now prefers the documented nested spelling over the flat one — that is the setting a user reads in the docs. - ② follows one more file (`commondir`) only when `<gitdir>/config` is absent, so a submodule reads exactly what it read before. A `.git` pointer with neither a `config` nor a `commondir` answers null, not a wrong path (asserted). - ③ narrows the accepted name space: a repository whose owner or name starts with `.` is now refused. GitHub does not allow such names, so nothing real is lost, and the refusal is the same "not a repository" answer as a non-GitHub host. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1261, "claim": "Dev4", "issue": 1258, "summary": "The delivery board now reads delivery.repo in the three shapes a profile can write it — nested, literal dotted, or flat deliveryRepo — instead of only the flat key, so the setting the hint and the docs name really names the repository. A linked git worktree resolves its origin through its commondir instead of falling back to the package default. A repository name with a leading dot segment is refused, since ../.. was accepted and produced /repos/../../issues. All three live in core/src/host/delivery-repo.js, with the board setting() calling the new reader.", "files": [ "core/src/host/delivery-repo.js", "core/src/host/delivery-board.js", "core/test/delivery-repo.test.js", "core/test/delivery-board.test.js", "docs/subsystems/core-host.md", "changelog.d/1258-delivery-repo.fixed.md" ], "checks": { "ran": "node scripts/ds-bot-patches.mjs check; node scripts/build-client.mjs --check; ten core suites (113 tests) incl. delivery-repo; arch-docs; oxlint; changelog; mojibake; three knives", "result": "green", "at": "5d1483ca21c4a3a02207d143cf7e87f8d90e3492" }, "next": "none — ready for review" } ``` <!-- /flybot:checkpoint -->
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.
Fixes #1250
Owner: Dev4
Reviewer: Reviewer
Written-by: Dev4
Tip SHA:
cd907943d0bd39c0cea8cfacb88e82b394d98829Reproduce
An instance that is not this repository showed this repository's numbers and said nothing about whose they were. At
0b2a9859the board tookrepoonce at install:repoSlug()parses the shipped package'srepository.url(core/src/host/update.js:163) and nothing in the tree assignsrt.repoSlug, so every instance read/repos/ThinkFlowLab/FlyBot. A fork instance, or one with no token, showed our board.What changed
One resolver,
core/src/host/delivery-repo.js, imported by the host and bycore/scripts/delivery-probe.mjs(two call sites, one implementation, so they cannot drift):delivery.repo(config.deliveryRepo) → the team workspace's[remote "origin"] urlread straight out of.git/config→ the package'srepository.urlas a labelled default. No process is spawned; a.gitfile is followed through itsgitdir:. A name is normalised fromowner/name, a GitHub URL,git@github.com:owner/name.gitorssh://…; another host is refused rather than mined.install()resolves{ repo, source }on everyrt.deliveryBoard()call and keepsMap<repo, board>: a changed setting gets a new board whose first read isloading, never the previous repository's columns.state: 'failed'withno repository — set delivery.repobefore a board exists and before any request — no/repos/null.acme/widget · from config/from remote/from the package (default), the Diagnose text names the source, and ano-repohint points atdelivery.reporather than at the token.#1211failure shape and its message names the repository and the endpoint.core-host(resolver row + how the board resolves),core-client(the header line),install(--workspaceand the shared resolver), changelog fragment.patches/ds-bot/0001and0008regenerated; the generator moved thesteward.jsblock in0001to its alphabetical place — same 52 file sections, content identical,checkgreen.What I ran
Tip SHA:
cd907943d0bd39c0cea8cfacb88e82b394d98829delivery-repo.test.jsis the table-driven knife: config wins over a disagreeing remote, all four remote URL forms, thegitdir:file,originonly, package last, none at all, and the probe shell's own order.delivery-board.test.jsholds the install wiring: config → both board and probe readacme/widgetwithrepoSource: 'config'; the workspace remote →'remote'; a changed setting →loading; package →'package'and exactly one(default)warning; no repository → zero requests; a 404 namesacme/widgetand/repos/acme/widget/issues.Red without the source change
Two knives, each removing one branch of
resolveRepo():delivery.repo in the instance setting answers first…,the instance setting names the repository for the board and the probe…,a changed setting re-resolves…,a repository the token cannot read fails naming…, and the pre-existingthe token is read per request…(its host fixture now names the repository through the setting).the workspace origin answers…,an origin written as a URL, an scp path or a name with no .git reads the same,a .git file is followed through its gitdir…,only origin counts…,the workspace git remote names the repository….Restored, both suites are 109/109 again.
Both knives are one deletion in
core/src/host/delivery-repo.js:84-91— a reviewer can re-run them without reading the tests:Restore with
git checkout -- core/src/host/delivery-repo.js; the same file is mirrored underpatches/ds-bot/files/, so undo the knife beforenpm run ds-bot-patches check.Not run
npm teston this box: it hitsspawn … EAGAIN/pthread_create: Resource temporarily unavailableunder the whole suite; CINode 24is the reference.npm run verifyas one command, for the same reason — its steps (build check, patch check, arch-docs, oxlint, suites) were run individually above.enqueue-guardas a whole: its CLI does not start on this box (spawnSync gh ENOENT), so only its checkpoint half was run here —checkpointReasons(body, { pr: 1255, files })imported from.github/scripts/enqueue-rules.mjsagainst this pull request's 22 changed paths returns[]. The guard's own reason on this head isno Verifier report names the tip cd907943d0bd.Risk
delivery.repo; a workspace that is not a git checkout falls to the package default, which the header labelsfrom the package (default)instead of presenting as fact.delivery.repois a new instance key. Without it, behaviour is unchanged except that the fallback is now visibly a default and is logged once.repositoryfield now fails with the named message rather than showing another repository's numbers — intended, and asserted with zero requests.Checkpoint
{ "pr": 1255, "claim": "Dev4", "issue": 1250, "summary": "One resolver (core/src/host/delivery-repo.js), shared by the host and core/scripts/delivery-probe.mjs: delivery.repo (config.deliveryRepo) first, then the team workspace's git origin from .git/config, then the package's repository.url labelled as a default. The board keeps one instance per repository, so a changed setting starts its new repository at loading; nothing resolving refuses with a stated message before any request, never /repos/null. The header and the Diagnose text name the repository and its source.", "files": [ "core/src/host/delivery-repo.js", "core/src/host/delivery-board.js", "core/src/client/delivery-view.js", "core/src/client/i18n.js", "core/scripts/delivery-probe.mjs", "core/test/delivery-repo.test.js", "core/test/delivery-board.test.js", "core/test/delivery-view.test.js", "docs/subsystems/core-host.md", "changelog.d/1250-delivery-repo.added.md", "core/client.js", "patches/ds-bot/0001-core-fixes.patch" ], "checks": { "ran": "node scripts/ds-bot-patches.mjs check; node scripts/build-client.mjs --check; node --import ./test/harness-resolve.mjs --test --test-concurrency=1 (10 suites incl. delivery-repo, 109 tests)", "result": "green", "at": "cd907943d0bd39c0cea8cfacb88e82b394d98829" }, "next": "none — ready for review" }