Say which build to run inside the devcontainer - #125
Conversation
Reviewer's GuideAdds explicit devcontainer-specific guidance to AGENTS.md about which devlaunch build to run inside this repo’s devcontainer (use the editable checkout via File-Level Changes
Assessment against linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
AGENTS.md's two-install advice reads as universal, and an agent working inside this repo's devcontainer who follows it runs ./dev.sh and gets 'Error: uv is not installed', with nothing to fall back on. Say what is true in there instead: one build, the checkout, reached as pixi run dl and pixi run aid. The reason is which devpod dl finds, rather than naming. devpod injects its own agent binary onto the bare PATH of every container it creates, so a devlaunch outside the project env has a devpod to drive when the container was opened by devpod and none when it was opened by VS Code -- working or not by how you got in. The project env's devpod is there on both routes and is the version the tree is pinned against. Three of the section's claims are load-bearing and can go stale without anyone noticing, so they get checks: that dev.sh really does refuse before touching a path when uv is absent, that the container really does arrive with the checkout installed editable, and that the provenance string the example quotes is the one --version emits.
c3becd3 to
97962c8
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #125 +/- ##
=======================================
Coverage 90.68% 90.68%
=======================================
Files 18 18
Lines 1987 1987
=======================================
Hits 1802 1802
Misses 185 185 🚀 New features to boost your workflow:
|
blooop
left a comment
There was a problem hiding this comment.
This was generated by AI during review.
Reviewed in fresh context, against merge-base 85e27b1. Diff is two files (AGENTS.md, test/test_agents_doc.py); .devcontainer/ is untouched. All 9 checks green.
This PR is mostly prose, so it was reviewed as prose: are the claims true, and will a reader act correctly on them? Every load-bearing claim was re-measured independently rather than taken from the PR body.
Standards
The rewritten devpod argument holds. Both halves verified on metal, independently.
Presence. Two live devpod-created containers on this host:
$ docker exec <devlaunch-main-zovomobo> sh -c 'command -v devpod; ls -l /usr/local/bin/devpod; devpod version'
/usr/local/bin/devpod
-rwx--x--x 1 root root 117940408 /usr/local/bin/devpod
v0.26.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Root-owned, mode 711, on the bare PATH, a working CLI. #99's draft ("no devpod to drive and dies on the lookup") is indeed false, and the refutation was right to be made.
Absence — the half the PR asserted rather than measured. Probed the image the devcontainer is built from:
$ docker run --rm --entrypoint /bin/sh <devlaunch devcontainer image> -c 'ls /usr/local/bin; command -v devpod'
code devcontainer-info git git-* gitk pixi scalar systemctl
devpod: NOT IN IMAGE
Nothing in .devcontainer/Dockerfile (pixi only) or the claude-code feature (pixi + claude) installs devpod. So the binary is injected post-create by devpod, and an entry route that is not devpod — VS Code or devcontainer up, same image — yields nothing at that path. The entry-path argument is sound as written, and the corrected reasoning is better than what it replaced.
Two notes on method rather than conclusion. First, the PR measured only the presence half; the VS Code half — the half the whole argument turns on — shipped as an inference. Under this map's verify on metal that is the shape of the failure the map exists to prevent. It happens to be true; it was one docker run --rm away. Second, a PR-body over-generalization: "its mtime is the moment the container was created" is not a general property. devlaunch-main-zovomobo was created 2026-08-07T22:36:22Z and its binary's mtime is Aug 8 08:42 — devpod re-injects the agent on later operations, so the mtime is last injection, not create time. This does not appear in AGENTS.md and if anything strengthens the "present because devpod is driving this container" framing.
Other claims in the new section, each checked:
| Claim | Result |
|---|---|
dl shells out to a bare devpod from PATH |
✅ cmd = ["devpod"] + args, dl.py:843 and :866 |
uv is not installed in the container |
✅ command -v uv → none in a live devcontainer; uv appears nowhere in pyproject.toml |
pixi run aid works inside |
✅ aid = "devlaunch.aid:main" in [project.scripts]; aid present in .pixi/envs/default/bin/ |
| the pinned devpod is the version the tree is written against | ✅ devpod = ">=0.26.1,<0.27" |
"devpod 0.8 asks for a pty on ssh --command and 0.26 never does" |
✅ matches pyproject.toml's own pin comment and CHANGELOG 0.0.13 |
| the project env's devpod is present on both entry routes | ✅ postCreateCommand runs on both |
Finding 1 — the quoted version already contradicts its neighbour (comment). The new section quotes dl 0.0.16 (dev, editable from /workspaces/<checkout>) three paragraphs below the host bullet, which still quotes dl 0.0.9 (dev, editable from /path/to/checkout); README.md:~326 also says 0.0.9. Two different versions in two examples of the same string inside one section is exactly the rot this PR's tests exist to prevent, and test_the_provenance_example_matches_what_version_prints pins the phrase but not the version, so nothing catches it. Cheapest fix: drop the number (dl <version> (dev, editable from /workspaces/<checkout>)).
Finding 2 — the -next sentence argues against something the document does not claim (comment). "printing the same provenance string as pixi run dl, so the one property the two-install convention rests on — being able to tell the builds apart — would not exist." Two paragraphs up, the convention rests on "names that cannot collide", and dl-next vs pixi run dl are still different names. The true point is that the two would be the same build, so there is nothing to tell apart and nothing to gain — not that naming stopped working. Inherited verbatim from #99's draft; one sentence of repair.
The seven tests
Red-before-green verified rather than accepted: the module was run against a detached worktree at 85e27b1 — exactly 3 failed, 4 passed, matching the claim. The other four pin pre-existing facts the new prose now depends on, which is a legitimate reason to write them.
test_dev_sh_refuses_before_touching_anything_when_uv_is_absent is the strongest of the seven and the model for the rest: real subprocess, real script, asserting exit status, message, and absence of side effects. It is the one claim in the section that a code change could actually invalidate. Keep as is.
Three tests pin less than their names promise:
Finding 3 — test_the_provenance_example_matches_what_version_prints has one brittle assertion and one inert one (comment).
assert 'f"dev, editable from {tree}"' in sourcepins the source spelling, not the emitted string. Renaming the localtree→path— a no-op refactor — turns it red while the documented output is unchanged; conversely it never exercisesdl.py:133, where the string is actually composed. A behavioral assertion on_install_provenance()costs the same line.assert "dev, editable from" in _container_section()followed byassert "dev, editable from" in _agents_md(): the section is a substring of the document, so the second can never fail independently. The docstring says it checks "both the section and the host advice"; it does not check the host advice at all — and that is precisely the assertion that would guard amendment 2's fix in the host bullet.
Finding 4 — test_agents_md_warns_off_dev_sh_inside_the_container cannot tell a warning from an instruction (comment). It asserts "./dev.sh" in section and "uv" in section. A section that said run ./dev.sh passes. Pin the imperative the reader must obey: **Do not run ./dev.sh**.
Finding 5 — _container_section() fails unhelpfully on the failure mode it will actually hit (nit). When the heading changes, text.index(...) raises ValueError: substring not found and three tests die on a stack trace pointing at .index (observed at 85e27b1). One assert CONTAINER_HEADING in text, "…" makes it self-explanatory.
Finding 6 — the postCreateCommand regex assumes the string form (nit). devcontainer.json also permits an array or object; adding a second step as an array makes the test report "devcontainer.json declares no postCreateCommand" — a false diagnosis of a still-correct config.
Also minor: for tool in ("dirname",): is a one-element loop (speculative generality); and the hardcoded .local/share/devlaunch-dev / .local/bin duplicate dev.sh's paths, so if dev.sh moved them those two assertions go vacuous — the exit-code and message assertions still carry the test.
test_claude_md_is_the_same_document_as_agents_md (cheap, exact, guards a real hazard), test_agents_md_sends_in_container_work_through_pixi_run (thin but pins the one actionable instruction, correctly scoped to the section) and test_agents_md_does_not_claim_version_hides_provenance (a negative pin that can only catch re-introduction of two exact phrasings — which is what the PR table honestly says it is) all earn their place.
tomllib → tomli fix confirmed correct: tomllib is stdlib from 3.11 and ci (py310) is in the matrix; tomli>=2.0.0 is already a runtime dependency (devlaunch/worktree/config.py:8), so no new dependency was taken. grep -rn tomllib over the branch → zero hits.
Placement (test/test_*.py top level) and markers (unit / integration, both registered, both run in CI) match repo convention. No Fowler smell worth acting on. Ruff/pylint/ty already gate the rest.
Spec
Spec is #116, which carries #99's undischarged obligations.
The answer: inside, run
pixi run dlandpixi run aid.
✅ Delivered, under its own heading, with the premise the ticket states — devlaunch = { path = ".", editable = true } plus postCreateCommand running pixi install — and both halves now tested.
Amendment 1 — drop the proposed final paragraph. … Do not include it.
✅ Confirmed absent. No XDG string anywhere in the added text; #119 landed the deletion the amendment anticipated, so there is no hazard left to caveat.
Amendment 2 —
AGENTS.mdstill says--versionreports no provenance.
✅ The author is right, and the spec's premise is wrong. Verified independently: fda3cb3 ("Tell an editable dl install apart from a released one", 2026-08-07 23:12) is an ancestor of origin/main, and origin/main:AGENTS.md reads "dl-next --version names the tree it resolves to — dl 0.0.9 (dev, editable from /path/to/checkout) … told apart by output as well as by name." The stale sentence survives only at older commits — including b304cb6, an ancestor of main and the commit the primary checkout is parked on, which still reads "the package version, not its provenance … the name is the only thing distinguishing the two." Reporting the finding instead of inventing an edit was the correct call, and pinning it with a test was the right substitute.
Before this closes, paste into the PR:
pixi run dl --version, onepixi run dl <repo>,command -v uv || echo none.
✅ All three present. Two re-derived here: uv absent from a live devcontainer and from pyproject.toml; f"dev, editable from {tree}" at dl.py:122. The 36.7s dl blooop/dotfiles run was not reproduced — that means building a dind container on a shared host — and is accepted on the transcript; its shape is consistent with #96's measured 25.2s cold / 7.9s warm.
The devcontainer.json separation held. git diff 85e27b1...HEAD --name-status returns only AGENTS.md and test/test_agents_doc.py; .devcontainer/ shows an empty diff, and main's file still has the dind feature commented out. Using origin/feat/devcontainer-dind's version locally for the daemon-requiring measurement leaked nothing into the diff.
say plainly in the PR which parts are covered and which rest on the pasted transcripts
✅ The coverage table plus the explicit "Not covered by a test, and resting on the transcripts below" paragraph does this better than asked.
Proposed CHANGELOG entry — accurate, and in the repo's voice. Every checkable claim in it holds: the injection is real (measured above), the uv consequence is real, "the version the tree is pinned against" matches devpod = ">=0.26.1,<0.27". Voice matches 0.0.16 and 0.0.14: one long ### Changed bullet, mechanism before consequence, and the closing "Nothing about dl on a host changes, and the two builds the section already described are unaffected" is the house formula. Scoping it as a fragment for the merge train to place, without a release lead paragraph, is correct — the lead is per-release and not this PR's to write. No defect; the absent version bump is deliberate and not counted against it.
Host hygiene — the devpod delete call was right, and I would have made it. Two independent supports in the repo's own record: #101 measured that devpod's DeleteDevContainer is a plain docker rm without -v and DeleteVolume has zero callers, so delete demonstrably leaks the volume — removing container + volumes + image by hand does reclaim strictly more, exactly as claimed; and delete rewrites the shared ~/.ssh/config, which #112 is open about. Verified the outcome: no wf116-* container, image or volume remains, and the only dind volume left is dind-var-lib-docker-default-wf-9ef1b, created 2026-08-08T09:45:59+01:00 — pre-dating the run, as stated.
Host state, before and after this review: ~/.ssh/config md5 0fcb9aeff46aad62551d9d688f2021f7, unchanged; no dotfiles-main-dizipeja or wf116 block present, so the targeted ten-line removal was complete. devpod list shows the same six workspaces before and after. The author's recorded 8a4da6f3… → 0fcb9aef… (46 → 56 lines) lands on the value still present, and their attribution of the +10 lines to a concurrent agent checks out: lines 1–10 are the bencher-test1-pipagito.devpod block, whose workspace is live and is not theirs.
Verdict
Approve — with six comments, none blocking.
The headline call was correct twice over: the draft's stated reason really was false, and the replacement really is sound — I verified the half the PR did not. Amendment 2's claim about main is right, and declining to invent an edit was better practice than making one. Nothing false ships.
Non-blocking, worth fixing before or after merge:
- The section quotes
0.0.16three paragraphs below a bullet quoting0.0.9— drop the number. - The
-nextsentence argues that names stop distinguishing the builds; they do not. The point is that the builds would be identical. test_the_provenance_example_matches_what_version_prints: pins an f-string's source spelling, and its second assertion is implied by its first, so the host-advice half is unguarded.test_agents_md_warns_off_dev_sh_inside_the_containerpasses on a section that says the opposite of what it means._container_section()should assert its heading rather than raiseValueError.- The
postCreateCommandregex misreports the array form as "declares no postCreateCommand".
Nothing here belongs to /tdd; 1–2 are one sentence each and 3–6 are four lines of test.
Three of the seven tests passed on text that says the opposite of what they claim to check, which is worse than not having them: they buy confidence while still breaking on a reword. The provenance test pinned an f-string's *source spelling*, so renaming a local turned it red without ever running the line that composes the string, and its second assertion was a substring of its first, leaving the host advice it named unguarded. It now feeds the real `_install_provenance()` the PEP 610 record pip writes for an editable install and compares the emitted line against the one the document quotes, parametrized over host and container so each is checked alone. The `./dev.sh` test asserted only that `./dev.sh` and `uv` appeared, so a section telling the reader to *run* it would have passed. It now pins the prohibition itself. `_container_section()` raised `ValueError: substring not found` on a renamed heading, so every test using it lied about why it failed; it now says which heading is missing. The `postCreateCommand` regex reported a valid array form as "declares no postCreateCommand". Two prose fixes: both `--version` examples say `dl <version>` rather than drifting apart at each release, as `0.0.9` and `0.0.16` already had; and the `-next` sentence no longer claims naming stops distinguishing the builds when the point is that the builds would be identical.
|
All six addressed in The common thread in 3–6 is the one the review named: a doc test that passes when the doc says the opposite is worse than no test. So each changed assertion was run against text that should fail it, rather than just re-read. 1. The quoted version (
2. The
3. def _provenance_for(tree: str) -> str:
direct_url = json.dumps({"url": Path(tree).as_uri(), "dir_info": {"editable": True}})
with mock.patch("devlaunch.dl.distribution", return_value=_FakeDist(direct_url)):
provenance = _install_provenance()
...
@pytest.mark.parametrize("tree,section", DOCUMENTED_PROVENANCE_EXAMPLES)
def test_the_provenance_example_matches_what_version_prints(tree, section):
expected = f"`dl <version> ({_provenance_for(tree)})`"
assert expected in section(), f"AGENTS.md no longer quotes {expected} for {tree}"Parametrized over Three mutations, since this test had to stop doing one thing and start doing another: The no-op refactor the review predicted would break it — must stay green: The emitted message changed — must go red, both examples: Only the host bullet broken — proves the independence the old version lacked: 4. assert re.search(r"\*\*Do not run `\./dev\.sh`[^*]*\*\*", section), (
"the in-container section no longer forbids `./dev.sh` in bold"
)
assert "`uv` is not installed" in sectionThe 5. Two tests, one message each, pointing at the cause instead of at 6. The and a genuine absence still diagnoses correctly: Also taken: Deliberately not changed: the hardcoded PR body: the mtime over-generalization is corrected there — last injection, not create time, with All mutations were applied to a backed-up copy and restored; |
Closes #116
AGENTS.md's two-install section reads as universal advice. It is not: an agentworking inside this repo's devcontainer who follows it runs
./dev.sh, getsError: uv is not installed, and has nothing to fall back on. This appends onesection saying what is true in there — one build, it is the checkout, and it is
reached as
pixi run dl/pixi run aid— and gives three of its load-bearingclaims a test so they cannot rot quietly.
CLAUDE.mdis a symlink toAGENTS.md; onlyAGENTS.mdis edited.What changed against #99's draft
The wording is #99's, with the ticket's two amendments applied and one paragraph
rewritten because the metal contradicted it.
Amendment 1 — dropped, as instructed. The draft's final paragraph explained
that the scratch-
XDGrecipe is host-only becauseXDG_CONFIG_HOMEisload-bearing inside the container. #119 has since deleted
XDG_CONFIG_HOMEfromthat recipe outright and written down the trade it makes, so there is no longer a
hazard to caveat. Including the paragraph would have documented one that no longer
exists.
Amendment 2 — the stale claim was already gone. The ticket asks for a fix to
AGENTS.mdstill saying--versionreports no provenance. Onmainit does not:fda3cb3("Tell an editable dl install apart from a released one", PR #85) updatedthat bullet in the same commit that landed the feature, and it now reads
dl 0.0.9 (dev, editable from /path/to/checkout)— the two builds told apart byoutput as well as by name. The stale sentence survives only in checkouts sitting on
older commits, which is the likeliest source of the report. No edit was needed,
so none was invented. A test pins it shut instead, since the new section's own
example depends on it.
The devpod paragraph is rewritten, and this is the substantive change. #99's
draft said:
That is false on metal.
command -v devpodinside the container answers/usr/local/bin/devpod, and it is a working CLI —version,provider listandlistall respond. It is root-owned, mode 711, and its mtime is devpod's lastinjection rather than the container's creation —
devlaunch-main-zovomobowascreated
2026-08-07T22:36:22Zand carries anAug 8 08:42binary, because devpodre-injects the agent on later operations. It is the agent binary devpod injects
into every workspace it makes, and keeps current for as long as it drives it,
which is a tighter tie to devpod than a create-time stamp would be. A devlaunch
installed outside the project env would have found it.
The conclusion survives and the corrected reason is stronger, because it is about
the entry path rather than about absence. That binary is there because devpod
created this container. Open the same devcontainer through VS Code or a plain
devcontainer upand nothing injects it — so a devlaunch outside the project envdrives a devpod on one route in and none on the other, which is worse to diagnose
than never working at all. What
pixi runbuys is a devpod that is present on bothroutes and is the version the tree is pinned against, rather than whatever the host
happened to inject. Two further measurements went in as a short second paragraph:
the pinned devpod and the injected one match in version here only because this
host runs the version the tree pins — nothing keeps them equal — and both read
the same
~/.devpod, so choosing between them is not an isolation boundary and thesection should not let a reader think it is.
Test coverage, honestly
Most of this is prose and gets no test; inventing one for a paragraph would be
theatre, and #116 says so. What
test/test_agents_doc.pycovers is the handful ofstatements a reader would act on that the repository could silently invalidate:
./dev.shrefuses, before touching a path, whenuvis absentuvoffPATHagainst a throwawayHOME, and asserts exit 1, the message, and that neither~/.local/share/devlaunch-devnor~/.local/binwas created./dev.sh's job donepyproject.tomldeclares the editable self-dependency anddevcontainer.json'spostCreateCommandrunspixi installdev, editable from …is what the code emits_install_provenance()is run against the PEP 610 record pip writes for an editable install, and the line it composes is compared with the one the document quotes — host and container checked separately./dev.shis forbidden inside, not merely mentionedpixi runpixi run dlandpixi run aidboth named under the new headingCLAUDE.mdis still a symlink toAGENTS.mdNot covered by a test, and resting on the transcripts below: that
pixi run dlis the invocation that works inside, that
dl <repo>succeeds from in there, andthat no released fallback is wanted. Those are claims about a built container, not
about this tree.
Full suite green locally: 988 passed, 22 deselected (
pixi run test) as firstpushed; the review round below parametrizes one of these tests in two, so the count
is one higher from
11d9f22on.pixi run styleclean — ruff format, ruff check,ty, pylint 10.00/10.The metal obligation
#116 carries #99's undischarged test obligation. All three checks were run, plus
two more that were worth having.
A devcontainer was built for this.
main's.devcontainer/devcontainer.jsonstillhas the dind feature commented out, so for the
dl <repo>check the container wasbuilt from
origin/feat/devcontainer-dind's version of that one file — the diff#109 is landing. That file is not touched by this PR; it was a local swap for
the measurement only. The
--version,uvanddev.shchecks need no daemon andwould have been identical on
main's file.Everything ran under a scratch
DEVPOD_HOME/DEVPOD_SSH_CONFIG, from a copy ofthis branch named
wf116-doc, and was removed afterwards.1.
pixi run dl --version, from insideExactly the string the new section quotes.
2.
command -v uv, from insideThe
uv-absent claim holds on metal. And the consequence, run rather thanasserted:
Clean and loud, nothing half-installed — the refusal the section calls correct.
3.
pixi run dl <repo>, from insideNeeds a daemon, and had one (
docker versioninside reports server29.7.1-1against the host's
29.5.2). The docker provider was added inside first;dldoesnot add it.
blooop/dotfileswas used rather than this repo, so the check measuresdlrather than a nested pixi build.Clone → id → workspace → ssh → exit 0, cold, three levels down.
4. The measurement that changed the wording
5. An isolation leak worth recording — already known from #96, reconfirmed
here. The devcontainer bind-mounts
${localEnv:HOME}/.ssh, so the nesteddevpod upthe check above performed wrote its host block into the host's~/.ssh/config, with aProxyCommandnaming a path that exists only inside thecontainer:
Removed by hand afterwards. Not this PR's to fix; noted so the next prototype
expects it.
Host hygiene
DEVPOD_HOMEandDEVPOD_SSH_CONFIG; the host's real workspace list wasnever in scope and
devpod liston the host is unchanged.~/.ssh/configbefore the run:8a4da6f37505c9cfb325ab92b8ce5497(46 lines).After cleanup:
0fcb9aeff46aad62551d9d688f2021f7(56 lines). The delta is notfrom this run — it is one block a concurrently running agent added for
bencher-test1-pipagito, whose container is still up. The only block this runadded (
dotfiles-main-dizipeja, from the nestedup) was removed by a targetededit, verified by diff against a snapshot: exactly ten lines, all of them that
block.
devpod deletewas deliberately not used. With other agents working on thishost, a delete that rewrites the shared
~/.ssh/configrisks their blocks;removing the container, its two volumes and its image directly reclaims strictly
more (
devpod deletedoes not reclaim the dind volume) and touches nothingshared.
wf116-doc, imagewf116-doc-40365:devpod-…,volumes
wf116-doc-pixianddind-var-lib-docker-default-wf-41361, and thescratch devpod home. A second dind volume (
…-wf-9ef1b, created 09:45, hoursbefore this run) was left alone.
Review round: the three tests that passed on the wrong text
11d9f22answers the six non-blocking comments on the approval. The theme is thata doc test which passes when the doc says the opposite is worse than no test — it
buys confidence and still breaks on a harmless reword. Three of the seven were in
that shape.
test_the_provenance_example_matches_what_version_printspinned thef-string's source spelling, so a
tree→pathrename went red without everrunning the line that composes the string, and its second assertion was a
substring of its first, so the host advice it named was unguarded. It now feeds
the real
_install_provenance()the PEP 610 record pip writes for an editableinstall and compares what it emits against what the document quotes,
parametrized over the host bullet and the container section so each stands alone.
test_agents_md_warns_off_dev_sh_inside_the_containerasserted only that`./dev.sh`anduvappeared, so a section telling the reader to run itpassed. It now pins the bold prohibition and the reason.
_container_section()raisedValueError: substring not foundon a renamedheading, so every test using it lied about why it failed; it now names the
missing heading. The
postCreateCommandregex reported a valid argv-arrayform as "declares no postCreateCommand"; both forms are accepted.
--versionexamples now readdl <version> (…)rather thandrifting apart at each release, which
0.0.9and0.0.16already had. The-nextsentence no longer claims naming stops distinguishing the builds — thedocument itself rests that convention on names that still differ; the point is
that the two builds would be identical.
injection, not create time.
Each changed assertion was checked against text that should fail it — an inverted
./dev.shinstruction, a changed provenance message, a host-only example break, arenamed heading, an argv-array
postCreateCommand— and each failed for the statedreason, with
git diffclean of the mutations afterwards.Proposed CHANGELOG entry
Not applied here — four PRs are in flight and four version bumps would collide.
For whichever release picks this up:
Changed
AGENTS.mdsays which build to run inside this repo's devcontainer, instead ofleaving the host's two-install advice to be followed in a place it does not work.
There is one build in there and it is the checkout — the devcontainer installs it
editable at create time — so the answer is
pixi run dlandpixi run aid, and./dev.shshould not be run in there at all: it exits at its first check becausethe container has no
uv, which is the right outcome rather than a gap to fill.The reason
pixi runmatters is which devpoddlfinds. devpod injects its ownagent binary onto the bare
PATHof every container it creates, so a devlaunchinstalled outside the project environment finds a devpod when the container was
opened by devpod and none when it was opened by VS Code — intermittent by how you
got in. The project environment's devpod is present either way and is the version
the tree is pinned against. Nothing about
dlon a host changes, and the twobuilds the section already described are unaffected.
🤖 Generated with Claude Code
Summary by Sourcery
Clarify how agents should run DevLaunch inside this repo’s devcontainer and add tests that pin the key behavioural and documentation assumptions in place.
Documentation:
pixi run dl/pixi run aid, and why./dev.shand a separate host-installed devlaunch are inappropriate inside the container.Tests:
pixi run dl/pixi run aidand warns against./dev.sh, dev.sh fails cleanly whenuvis absent, the devcontainer performs an editable self-install at create time, the documented provenance string matches whatdl --versionemits, and stale claims about--versionhiding provenance do not reappear.