Epic: os: the user, user folders, a child's environment (OS slice 6) #130

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

Goal

Slice 6 of docs/design/OS.md (section 10; signatures in sections 5.6 to 5.8): std/os answers who the user is and where the user's folders are, and a program can hand a child process an environment as a value. Windows, Linux, macOS and FreeBSD; the browser answers OsError.Unsupported where it has no user.

Specification

Steps (an epic: three PRs, each its own issue when it starts)

  • 1. The six user folders: Directories.documents/downloads/desktop/pictures/music/videos, the user-dirs.dirs parser, Known Folders, macOS (#531, landed). Pure TorbScript, no seed.
  • 2. The user (#537): User and User.current() (OS.md 5.7). POSIX over Posix.account and geteuid; Windows over GetUserNameExW and the process token (SID, elevation). New Windows natives; the compiler does not import User, so no seed refresh (like volumes, #128).
  • 3. A child's environment: Process.run, runBlocking, runPassingThrough and start gain environment: EnvironmentVariables? = None; None inherits. Both halves of torb_platform_run_process and torb_platform_child_start in runtime/platform.c take an environment block (POSIX environ/execve envp, Windows CREATE_UNICODE_ENVIRONMENT). The compiler itself calls Process.runBlocking, so this is the two-commit rule: commit 1 adds the natives (environment passed as a NAME=value ArrayList<String>) without using them, the seed is refreshed (Torben's), commit 2 gives the Process functions the parameter. Also: OS.md slice 6 marked done, docs/standard-library/os.md and docs/standard-library/process.md updated, skills/ regenerated.

Order: 1, 2, 3. Step 3 goes last because it waits for the seed refresh between its two commits. The step issues are filed just in time, one at a time.

Acceptance criteria (of the epic)

  • As OS.md 5.6 to 5.8 specify: every Directories function, User and User.current(), and environment: on the Process functions, on Windows, Linux, macOS and FreeBSD (FreeBSD's C stays uncompiled here, as OS.md slice 7 says); the browser answers Unsupported.
  • Every step lands with its own tests (pure parsers on every machine with captured input; host tests per system; a child that prints Environment.get of a variable set only through environment:, one that sees a removed variable gone, and one with None that sees the inherited environment).
  • torb check --every-target clean, docs check clean, skills/ regenerated.
  • OS.md slice 6 marked Done (date) with a short "How slice 6 landed" note of what differed from the design (the last step does this).

Seed impact

Step 1 and 2: no. Step 3: yes, a new native the compiler reaches through Process: two commits, the seed refresh in between is Torben's.

Size

Three PRs of one or two Conventional Commits each. One PR for all of it would touch std/os, std/process, runtime/platform.c, runtime/os/*.c and the seed in one go.

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

## Goal Slice 6 of `docs/design/OS.md` (section 10; signatures in sections 5.6 to 5.8): `std/os` answers who the user is and where the user's folders are, and a program can hand a child process an environment as a value. Windows, Linux, macOS and FreeBSD; the browser answers `OsError.Unsupported` where it has no user. ## Specification - Design record: [OS.md sections 5.6 (the environment), 5.7 (the user), 5.8 (well-known directories)](https://git.torb.dev/torbscript/language/src/branch/main/docs/design/OS.md#56-the-environment) and the slice 6 row of section 10. [docs/ROADMAP.md](https://git.torb.dev/torbscript/language/src/branch/main/docs/ROADMAP.md) lists `std/os` "the rest of their slices" (#126 to #131); this issue is slice 6. - Dependency: slice 1 (done) and #126 (closed). `Posix.account` (`getpwuid_r`) and `Windows.knownFolder` already exist. ## Steps (an epic: three PRs, each its own issue when it starts) - [x] 1. The six user folders: `Directories.documents/downloads/desktop/pictures/music/videos`, the `user-dirs.dirs` parser, Known Folders, macOS (#531, landed). Pure TorbScript, no seed. - [ ] 2. The user (#537): `User` and `User.current()` (OS.md 5.7). POSIX over `Posix.account` and `geteuid`; Windows over `GetUserNameExW` and the process token (SID, elevation). New Windows natives; the compiler does not import `User`, so no seed refresh (like volumes, #128). - [ ] 3. A child's environment: `Process.run`, `runBlocking`, `runPassingThrough` and `start` gain `environment: EnvironmentVariables? = None`; `None` inherits. Both halves of `torb_platform_run_process` and `torb_platform_child_start` in `runtime/platform.c` take an environment block (POSIX `environ`/`execve` envp, Windows `CREATE_UNICODE_ENVIRONMENT`). The compiler itself calls `Process.runBlocking`, so this is the two-commit rule: commit 1 adds the natives (environment passed as a `NAME=value` `ArrayList<String>`) without using them, the seed is refreshed (Torben's), commit 2 gives the `Process` functions the parameter. Also: OS.md slice 6 marked done, `docs/standard-library/os.md` and `docs/standard-library/process.md` updated, `skills/` regenerated. Order: 1, 2, 3. Step 3 goes last because it waits for the seed refresh between its two commits. The step issues are filed just in time, one at a time. ## Acceptance criteria (of the epic) - [ ] As OS.md 5.6 to 5.8 specify: every `Directories` function, `User` and `User.current()`, and `environment:` on the `Process` functions, on Windows, Linux, macOS and FreeBSD (FreeBSD's C stays uncompiled here, as OS.md slice 7 says); the browser answers `Unsupported`. - [ ] Every step lands with its own tests (pure parsers on every machine with captured input; host tests per system; a child that prints `Environment.get` of a variable set only through `environment:`, one that sees a removed variable gone, and one with `None` that sees the inherited environment). - [ ] `torb check --every-target` clean, `docs check` clean, `skills/` regenerated. - [ ] OS.md slice 6 marked **Done (date)** with a short "How slice 6 landed" note of what differed from the design (the last step does this). ## Seed impact Step 1 and 2: no. Step 3: yes, a new native the compiler reaches through `Process`: two commits, the seed refresh in between is Torben's. ## Size Three PRs of one or two Conventional Commits each. One PR for all of it would touch `std/os`, `std/process`, `runtime/platform.c`, `runtime/os/*.c` and the seed in one go. _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 OS.md slice 6, not a duplicate. Depends on #126. next: waiting (dependency #126) until 2026-10-10T04:00:00Z

[loop:torbscript] intake: in scope (author orion, label loop), source OS.md slice 6, not a duplicate. Depends on #126. next: waiting (dependency #126) until 2026-10-10T04:00:00Z
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261027 until 2026-10-27T05:45Z

[loop:torbscript] claim refine by session:loop-torbscript-20261027 until 2026-10-27T05:45Z
orion changed title from os: the user, user folders, a child's environment (OS slice 6) to Epic: os: the user, user folders, a child's environment (OS slice 6) 2026-10-27 03:43:08 +00:00
Author
Collaborator

[loop:torbscript] decided by the loop: slice 6 is an epic of three steps (folders, user, child environment), not one PR. Why: it touches std/os, std/process, runtime/platform.c (both halves) and, for the environment, the two-commit seed rule, because the compiler itself calls Process.runBlocking; the folders are pure TorbScript and need no seed. Order folders, user, environment: the step that waits for the seed refresh goes last.
[loop:torbscript] decided by the loop: the environment crosses the native boundary as a NAME=value ArrayList<String> (the manifest has no map shape), None means inherit, and environment: goes on run, runBlocking, runPassingThrough and start, not only on the two OS.md names, because one shared native body builds the block. The program name is looked up with this process's PATH on every system (Windows cannot do otherwise), and a doc comment says so.
[loop:torbscript] decided by the loop: Directories.videos() is ~/Movies on macOS (the Finder's name); a user-dirs.dirs key set to "$HOME/" means "this folder does not exist" in the XDG convention and falls back to the default instead of answering the home directory.

[loop:torbscript] decided by the loop: slice 6 is an epic of three steps (folders, user, child environment), not one PR. Why: it touches `std/os`, `std/process`, `runtime/platform.c` (both halves) and, for the environment, the two-commit seed rule, because the compiler itself calls `Process.runBlocking`; the folders are pure TorbScript and need no seed. Order folders, user, environment: the step that waits for the seed refresh goes last. [loop:torbscript] decided by the loop: the environment crosses the native boundary as a `NAME=value` `ArrayList<String>` (the manifest has no map shape), `None` means inherit, and `environment:` goes on `run`, `runBlocking`, `runPassingThrough` and `start`, not only on the two OS.md names, because one shared native body builds the block. The program name is looked up with this process's `PATH` on every system (Windows cannot do otherwise), and a doc comment says so. [loop:torbscript] decided by the loop: `Directories.videos()` is `~/Movies` on macOS (the Finder's name); a `user-dirs.dirs` key set to `"$HOME/"` means "this folder does not exist" in the XDG convention and falls back to the default instead of answering the home directory.
Author
Collaborator

[loop:torbscript] refine: made this an epic with three steps (checklist in the body, acceptance criteria, design record OS.md 5.6 to 5.8, seed impact, size) and filed step 1 as #531 (labels loop, ready; open issues searched for duplicates by "Process.run environment", "user-dirs", "User.current", "Known Folder", "documents downloads", "EnvironmentVariables": none; #128, #129, #131 are other slices). Steps 2 and 3 are filed just in time. Worker usage: one Sonnet RE worker, about 25 tool calls, no builds. next: waiting (epic: step 1 is #531, implement)

[loop:torbscript] refine: made this an epic with three steps (checklist in the body, acceptance criteria, design record OS.md 5.6 to 5.8, seed impact, size) and filed step 1 as #531 (labels `loop`, `ready`; open issues searched for duplicates by "Process.run environment", "user-dirs", "User.current", "Known Folder", "documents downloads", "EnvironmentVariables": none; #128, #129, #131 are other slices). Steps 2 and 3 are filed just in time. Worker usage: one Sonnet RE worker, about 25 tool calls, no builds. next: waiting (epic: step 1 is #531, implement)
Author
Collaborator

[loop:torbscript] claim refine (step 1 #531 landed, cut step 2) by session:loop-torbscript-20261028 until 2026-10-28T07:05Z

[loop:torbscript] claim refine (step 1 #531 landed, cut step 2) by session:loop-torbscript-20261028 until 2026-10-28T07:05Z
Author
Collaborator

[loop:torbscript] refine: verified step 1 on main (all six Directories functions, the user-dirs.dirs reading, host tests in std/os/tests/host.test.trb), ticked it in the body, and cut step 2 as #537 (labels loop, ready; goal, acceptance criteria, design record OS.md 5.7, seed impact none, size one PR of one or two commits). Duplicate search of open issues by "User.current", "User", "SID", "GetUserNameExW", "geteuid", "elevation": none. Step 3 is not filed yet (waits for #537 to land). Claim released. Worker usage: one Sonnet RE worker, about 8 tool calls, no builds. next: waiting (epic; step 2 is #537, implement)

[loop:torbscript] refine: verified step 1 on `main` (all six `Directories` functions, the `user-dirs.dirs` reading, host tests in `std/os/tests/host.test.trb`), ticked it in the body, and cut step 2 as #537 (labels `loop`, `ready`; goal, acceptance criteria, design record OS.md 5.7, seed impact none, size one PR of one or two commits). Duplicate search of open issues by "User.current", "User", "SID", "GetUserNameExW", "geteuid", "elevation": none. Step 3 is not filed yet (waits for #537 to land). Claim released. Worker usage: one Sonnet RE worker, about 8 tool calls, no builds. next: waiting (epic; step 2 is #537, implement)
Sign in to join this conversation.
No labels
loop
ready
No milestone
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#130
No description provided.