fs: Into<Path> signatures (PATH slice 2) #68

Open
opened 2026-10-05 21:07:16 +00:00 by orion · 15 comments
Collaborator

Context

std/fs takes Into<Path>, list answers List<Path>, IoError.path becomes a Path.

Source

Acceptance criteria

  • The signatures as PATH.md slice 2 specifies them
  • Callers in std and the compiler migrated
  • PATH.md slice 2 marked done

Dependencies

Slice 1 of PATH.md (std/path) and the checker condition for Into<Path> receivers are on main.

Steps (epic: no ready on this issue)

Too large for one PR (about 40 std/fs signatures, ~130 files import std/fs, IoError(...) is built at ~30 sites in std/fs, std/io, std/process and the compiler, and the lowering builds the IoError of a native from its path parameter). Each step becomes its own issue just in time:

  • 1. Teach the compiler: native parameters of type Into<Path>, IoError.path as Path (commit 1 of 2, seed rule) - #419 (landed as 23bfecf; the published seed 142293fd98 contains it)
  • 2. std/fs path parameters take Into<Path> (callers that pass a String or a literal keep working; return types and IoError.path unchanged) - #547 (landed, closed 2026-10-28)
  • 2b. systemPath, runtime half: torb_file_system_path and its manifest row (a new native, commit 1 of 2 of the seed rule) - #559 (landed as 4b3045d, closed 2026-10-29; the published seed 4b3045d313 contains it)
  • 2c. systemPath, std/fs half: public fn systemPath(path: Path): String over the native (commit 2 of 2; needs a published seed that contains 2b) - #580 (landed as PR #583, closed 2026-10-29)
  • 3. IoError.path becomes a Path: the construction and read sites in std/fs, std/io, std/process, compiler/, tools/ - #680
  • 4. list and absolutePath answer Path values: migrate the walkers that re-join names by hand; conformance programs of PATH.md section 6; PATH.md slice 2 marked done

Notes

Adds or changes a native, syntax or a name the compiler looks up: land it in two commits (teach both forms, refresh the seed, then migrate), as CLAUDE.md "Seed and breaking changes" says.

Moved from the planning lists of the docs; the design record stays the specification.

## Context `std/fs` takes `Into<Path>`, `list` answers `List<Path>`, `IoError.path` becomes a `Path`. ## Source - [PATH.md slice 2](https://git.torb.dev/torbscript/language/src/commit/393ef2608e4a60b8ff76d8b6b408951b822d887d/docs/design/PATH.md#L665) ## Acceptance criteria - [ ] The signatures as PATH.md slice 2 specifies them - [ ] Callers in `std` and the compiler migrated - [ ] PATH.md slice 2 marked done ## Dependencies Slice 1 of PATH.md (`std/path`) and the checker condition for `Into<Path>` receivers are on `main`. ## Steps (epic: no `ready` on this issue) Too large for one PR (about 40 `std/fs` signatures, ~130 files import `std/fs`, `IoError(...)` is built at ~30 sites in `std/fs`, `std/io`, `std/process` and the compiler, and the lowering builds the `IoError` of a native from its `path` parameter). Each step becomes its own issue just in time: - [x] 1. Teach the compiler: native parameters of type `Into<Path>`, `IoError.path` as `Path` (commit 1 of 2, seed rule) - #419 (landed as 23bfecf; the published seed 142293fd98fc contains it) - [x] 2. `std/fs` path parameters take `Into<Path>` (callers that pass a `String` or a literal keep working; return types and `IoError.path` unchanged) - #547 (landed, closed 2026-10-28) - [x] 2b. `systemPath`, runtime half: `torb_file_system_path` and its manifest row (a new native, commit 1 of 2 of the seed rule) - #559 (landed as 4b3045d, closed 2026-10-29; the published seed 4b3045d31334 contains it) - [x] 2c. `systemPath`, `std/fs` half: `public fn systemPath(path: Path): String` over the native (commit 2 of 2; needs a published seed that contains 2b) - #580 (landed as PR #583, closed 2026-10-29) - [ ] 3. `IoError.path` becomes a `Path`: the construction and read sites in `std/fs`, `std/io`, `std/process`, `compiler/`, `tools/` - #680 - [ ] 4. `list` and `absolutePath` answer `Path` values: migrate the walkers that re-join names by hand; conformance programs of PATH.md section 6; PATH.md slice 2 marked done ## Notes Adds or changes a native, syntax or a name the compiler looks up: land it in two commits (teach both forms, refresh the seed, then migrate), as `CLAUDE.md` "Seed and breaking changes" says. _Moved from the planning lists of the docs; the design record stays the specification._
Author
Collaborator

[loop:torbscript] intake: in scope (author orion, label loop), source PATH.md slice 2, not a duplicate, no collision with a design record. Changes signatures of std/fs that callers in std and the compiler use, so the two-commit rule applies if a name the compiler looks up changes; refine checks seed impact. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z

[loop:torbscript] intake: in scope (author orion, label loop), source PATH.md slice 2, not a duplicate, no collision with a design record. Changes signatures of `std/fs` that callers in `std` and the compiler use, so the two-commit rule applies if a name the compiler looks up changes; refine checks seed impact. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261023 until 2026-10-23T09:23:00Z

[loop:torbscript] claim refine by session:loop-torbscript-20261023 until 2026-10-23T09:23:00Z
Author
Collaborator

[loop:torbscript] refine: #68 is an epic, not one PR. PATH.md slice 2 is rated the highest-risk slice; it changes about 40 std/fs signatures and the type of IoError.path (built at ~30 sites in std/fs, std/io, std/process and the compiler), and the lowering builds an IoError from the native's path parameter, so the native side has to be taught first under the two-commit seed rule. Dependency checked: slice 1 (std/path) and the checker condition for Into<Path> receivers are on main, so nothing blocks. Keyword search of open and closed issues (Into, Path, IoError, std/fs, PATH) found no duplicate. #68 body now carries the four steps as a checklist and has no ready label. Filed step 1 just in time as #419 (loop, ready): native parameters of type Into<Path> and IoError.path as Path, commit 1 of 2, no std signature touched. Steps 2 to 4 follow one by one; step 2 waits for the seed refresh, which stays Torben's. next: implement #419

[loop:torbscript] refine: #68 is an epic, not one PR. PATH.md slice 2 is rated the highest-risk slice; it changes about 40 `std/fs` signatures and the type of `IoError.path` (built at ~30 sites in `std/fs`, `std/io`, `std/process` and the compiler), and the lowering builds an `IoError` from the native's `path` parameter, so the native side has to be taught first under the two-commit seed rule. Dependency checked: slice 1 (`std/path`) and the checker condition for `Into<Path>` receivers are on `main`, so nothing blocks. Keyword search of open and closed issues (Into, Path, IoError, std/fs, PATH) found no duplicate. #68 body now carries the four steps as a checklist and has no `ready` label. Filed step 1 just in time as #419 (`loop`, `ready`): native parameters of type `Into<Path>` and `IoError.path` as `Path`, commit 1 of 2, no `std` signature touched. Steps 2 to 4 follow one by one; step 2 waits for the seed refresh, which stays Torben's. next: implement #419
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261028 until 2026-10-28T16:22:28Z

[loop:torbscript] claim refine by session:loop-torbscript-20261028 until 2026-10-28T16:22:28Z
Author
Collaborator

[loop:torbscript] decided by the loop: step 1 (#419) is on main as 23bfecf (closed 2026-10-23), so the next step is std/fs parameters, filed just in time as #547 (loop, ready). Reasoning: (1) Seed: step 2 of the old checklist said "after the seed refresh", but the newest published seed (142293fd98, head of seeds.txt) already contains 23bfecf (git merge-base --is-ancestor), and CI bootstraps from the published seed, so no refresh by Torben is needed and nothing blocks. (2) Size: the old step 2 bundled the signatures with systemPath; systemPath needs a new native (runtime export of torb_platform_system_path as a String, manifest row), which is seed-touching under the two-commit rule, so it is split off as step 2b and #547 stays signatures only. (3) The IoError.path type, the list/absolutePath return types and the walkers stay out of #547; they are steps 3 and 4 (step 4 now names absolutePath too, as PATH.md section 6 lists it). Duplicate keyword search of open issues (Into, Path, std/fs, IoError, fs signature) found none; #146 (methods over free functions) is the only neighbour and does not cover these signatures. Checklist in the body updated: 1 ticked, 2 -> #547, 2b added. Owner decision: none, all internal and technical.

[loop:torbscript] decided by the loop: step 1 (#419) is on main as 23bfecf (closed 2026-10-23), so the next step is `std/fs` parameters, filed just in time as #547 (`loop`, `ready`). Reasoning: (1) Seed: step 2 of the old checklist said "after the seed refresh", but the newest published seed (142293fd98fc, head of seeds.txt) already contains 23bfecf (`git merge-base --is-ancestor`), and CI bootstraps from the published seed, so no refresh by Torben is needed and nothing blocks. (2) Size: the old step 2 bundled the signatures with `systemPath`; `systemPath` needs a new native (runtime export of `torb_platform_system_path` as a String, manifest row), which is seed-touching under the two-commit rule, so it is split off as step 2b and #547 stays signatures only. (3) The `IoError.path` type, the `list`/`absolutePath` return types and the walkers stay out of #547; they are steps 3 and 4 (step 4 now names `absolutePath` too, as PATH.md section 6 lists it). Duplicate keyword search of open issues (Into, Path, std/fs, IoError, fs signature) found none; #146 (methods over free functions) is the only neighbour and does not cover these signatures. Checklist in the body updated: 1 ticked, 2 -> #547, 2b added. Owner decision: none, all internal and technical.
Author
Collaborator

[loop:torbscript] refine: epic #68 verified against main (step 1 landed, seed contains it), next step filed as #547 and ready; 2b, 3 and 4 follow just in time, one after the other. next: ready (#547)

[loop:torbscript] refine: epic #68 verified against main (step 1 landed, seed contains it), next step filed as #547 and ready; 2b, 3 and 4 follow just in time, one after the other. next: ready (#547)
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261029 until 2026-10-29T01:13:11Z

[loop:torbscript] claim refine by session:loop-torbscript-20261029 until 2026-10-29T01:13:11Z
Author
Collaborator

[loop:torbscript] decided by the loop: step 2 (#547) is closed and on main (docs(fs) 877b4bdf, test(fs) 029f9449, the signatures before them), so the epic's next unblocked step is 2b, filed just in time as #559 (loop, ready). Reasoning: (1) Seed: torb_platform_system_path exists only as a Windows C function answering wchar_t * (declared under #if defined(_WIN32) in runtime/include/torb.h), and std/fs has no systemPath; a String-answering systemPath therefore needs a new native, which is seed-touching. Under the two-commit rule the native (runtime function plus manifest row) is commit 1 and the std/fs wrapper is commit 2, which needs a published seed containing commit 1. So 2b is split into #559 (runtime half, nothing in std/compiler//tools/ calls it) and a new checklist line 2c (the wrapper), which is filed only after the published seed contains #559. (2) Why not 3 or 4 first: they do not need a new native, but the epic orders systemPath before them and #559 touches only runtime/ and one manifest row, so it does not collide with them; 3 and 4 each rewrite many sites and follow one after the other. (3) Name: torb_file_system_path / fileSystemPath follow the torb_file_* and file* convention of the neighbouring private natives. (4) Duplicate keyword search of open issues (systemPath, system path, Into, IoError, std/fs): none besides #68; #146 is unrelated. Owner decision: none, all internal and technical.

[loop:torbscript] decided by the loop: step 2 (#547) is closed and on `main` (docs(fs) 877b4bdf, test(fs) 029f9449, the signatures before them), so the epic's next unblocked step is 2b, filed just in time as #559 (`loop`, `ready`). Reasoning: (1) Seed: `torb_platform_system_path` exists only as a Windows C function answering `wchar_t *` (declared under `#if defined(_WIN32)` in `runtime/include/torb.h`), and `std/fs` has no `systemPath`; a `String`-answering `systemPath` therefore needs a new native, which is seed-touching. Under the two-commit rule the native (runtime function plus manifest row) is commit 1 and the `std/fs` wrapper is commit 2, which needs a published seed containing commit 1. So 2b is split into #559 (runtime half, nothing in `std`/`compiler/`/`tools/` calls it) and a new checklist line 2c (the wrapper), which is filed only after the published seed contains #559. (2) Why not 3 or 4 first: they do not need a new native, but the epic orders `systemPath` before them and #559 touches only `runtime/` and one manifest row, so it does not collide with them; 3 and 4 each rewrite many sites and follow one after the other. (3) Name: `torb_file_system_path` / `fileSystemPath` follow the `torb_file_*` and `file*` convention of the neighbouring private natives. (4) Duplicate keyword search of open issues (systemPath, system path, Into<Path>, IoError, std/fs): none besides #68; #146 is unrelated. Owner decision: none, all internal and technical.
Author
Collaborator

[loop:torbscript] refine: epic #68 verified against main: steps 1 (#419) and 2 (#547) landed; checklist now ticks 2 and splits systemPath into 2b (runtime half, #559, filed and ready) and 2c (std/fs wrapper, after a published seed contains #559); 3 and 4 follow just in time, one after the other. The epic has no ready label. Claim by session:loop-torbscript-20261029 released. Worker usage: about 70k tokens (Sonnet 5.5 refine worker). next: ready (#559)

[loop:torbscript] refine: epic #68 verified against `main`: steps 1 (#419) and 2 (#547) landed; checklist now ticks 2 and splits `systemPath` into 2b (runtime half, #559, filed and `ready`) and 2c (`std/fs` wrapper, after a published seed contains #559); 3 and 4 follow just in time, one after the other. The epic has no `ready` label. Claim by session:loop-torbscript-20261029 released. Worker usage: about 70k tokens (Sonnet 5.5 refine worker). next: ready (#559)
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261029 until 2026-10-29T13:51Z

[loop:torbscript] claim refine by session:loop-torbscript-20261029 until 2026-10-29T13:51Z
Author
Collaborator

[loop:torbscript] decided by the loop: step 2b (#559) is closed and on main (PR #560, merge 4b3045d), so the epic's next unblocked step is 2c, filed just in time as #580 (loop, ready). Reasoning: (1) Seed: the newest published seed (4b3045d31334, head of seeds.txt) is the merge commit of #560 itself, so it contains the native torb_file_system_path and the manifest row fileSystemPath; the two-commit rule's "refresh the seed" step is done and 2c is commit 2 of 2, which touches no seed-relevant name and needs no further refresh. (2) Size: 2c is one public fn plus one private native fn declaration in std/fs, a test, and a PATH.md status sentence, one PR, one Conventional Commit (a second docs(fs) commit only if the skills regeneration is cleaner apart). (3) Why 2c before 3 and 4: it is the cheapest step, it is ready now, and it closes the systemPath strand of slice 2; steps 3 (IoError.path as Path, ~30 sites across std/fs, std/io, std/process, compiler/, tools/) and 4 (list, absolutePath and the walkers) rewrite many sites and should follow one after the other, not alongside. (4) Duplicate keyword search of open issues (systemPath, fileSystemPath, system path, Into, IoError, std/fs): none besides #68. Backlog gate: off (about 50 actionable against a limit of 1000), no ready issue without a PR was open, WIP is free. Owner decision: none, all internal and technical.

[loop:torbscript] decided by the loop: step 2b (#559) is closed and on `main` (PR #560, merge 4b3045d), so the epic's next unblocked step is 2c, filed just in time as #580 (`loop`, `ready`). Reasoning: (1) Seed: the newest published seed (`4b3045d31334`, head of `seeds.txt`) is the merge commit of #560 itself, so it contains the native `torb_file_system_path` and the manifest row `fileSystemPath`; the two-commit rule's "refresh the seed" step is done and 2c is commit 2 of 2, which touches no seed-relevant name and needs no further refresh. (2) Size: 2c is one `public fn` plus one private `native fn` declaration in `std/fs`, a test, and a PATH.md status sentence, one PR, one Conventional Commit (a second `docs(fs)` commit only if the skills regeneration is cleaner apart). (3) Why 2c before 3 and 4: it is the cheapest step, it is ready now, and it closes the `systemPath` strand of slice 2; steps 3 (`IoError.path` as `Path`, ~30 sites across `std/fs`, `std/io`, `std/process`, `compiler/`, `tools/`) and 4 (`list`, `absolutePath` and the walkers) rewrite many sites and should follow one after the other, not alongside. (4) Duplicate keyword search of open issues (systemPath, fileSystemPath, system path, Into<Path>, IoError, std/fs): none besides #68. Backlog gate: off (about 50 actionable against a limit of 1000), no ready issue without a PR was open, WIP is free. Owner decision: none, all internal and technical.
Author
Collaborator

[loop:torbscript] refine: epic #68 verified against main and the published seeds: steps 1 (#419), 2 (#547) and 2b (#559) landed and are ticked; the head seed 4b3045d313 contains 2b, so 2c is filed as #580 (loop, ready, no seed impact) and linked in the checklist. Steps 3 and 4 follow just in time, one after the other, after 2c. The epic has no ready label. Claim by session:loop-torbscript-20261029 released. Worker usage: about 60k tokens (Sonnet 5.5 refine worker). next: ready (#580)

[loop:torbscript] refine: epic #68 verified against `main` and the published seeds: steps 1 (#419), 2 (#547) and 2b (#559) landed and are ticked; the head seed 4b3045d31334 contains 2b, so 2c is filed as #580 (`loop`, `ready`, no seed impact) and linked in the checklist. Steps 3 and 4 follow just in time, one after the other, after 2c. The epic has no `ready` label. Claim by session:loop-torbscript-20261029 released. Worker usage: about 60k tokens (Sonnet 5.5 refine worker). next: ready (#580)
Author
Collaborator

[loop:torbscript] refine: 2c landed (#580, PR #583), ticked. Step 3 is filed as #680 (loop, ready); step 4 follows after it.
next: ready (#680)

[loop:torbscript] refine: 2c landed (#580, PR #583), ticked. Step 3 is filed as #680 (loop, ready); step 4 follows after it. next: ready (#680)
Author
Collaborator

[loop:torbscript] wait: step 3 is in work as #680. The worker found the seed 4b3045d313 cannot compile the full migration, so it opened the teaching half as PR #681 (native fileReadAllText, CI pending); the migration commit follows after a seed refresh. Step 4 comes after #680.
next: waiting (step #680, PR #681)

[loop:torbscript] wait: step 3 is in work as #680. The worker found the seed 4b3045d31334 cannot compile the full migration, so it opened the teaching half as PR #681 (native fileReadAllText, CI pending); the migration commit follows after a seed refresh. Step 4 comes after #680. next: waiting (step #680, PR #681)
Author
Collaborator

[loop:torbscript] wait: PR #681 (teaching half of step 3) is merged. The migration of #680 (IoError.path as Path) is ready as local patches but needs a seed that knows fileReadAllText: running the seed workflow on main is Torben's step (outside the loop). Step 4 comes after #680.
next: waiting (seed refresh by the owner, then the migration of #680)

[loop:torbscript] wait: PR #681 (teaching half of step 3) is merged. The migration of #680 (IoError.path as Path) is ready as local patches but needs a seed that knows `fileReadAllText`: running the `seed` workflow on main is Torben's step (outside the loop). Step 4 comes after #680. next: waiting (seed refresh by the owner, then the migration of #680)
Sign in to join this conversation.
No labels
loop
ready
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#68
No description provided.