package manager: record the variables an evaluated manifest read #29

Closed
opened 2026-10-05 21:07:12 +00:00 by orion · 7 comments
Collaborator

Context

The variables an evaluation read are printed by publish and recorded in the lock's from section, which is not written yet.

Source

Acceptance criteria

  • torb publish prints the environment variables the manifest's evaluation read
  • The lock's settings block records them in from
  • Documented in docs/tooling/project-lock-trb.md

Dependencies

None known.

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

## Context The variables an evaluation read are printed by `publish` and recorded in the lock's `from` section, which is not written yet. ## Source - [ROADMAP.md, the package manager](https://git.torb.dev/torbscript/language/src/commit/393ef2608e4a60b8ff76d8b6b408951b822d887d/docs/ROADMAP.md#L96) - [PROJECT.md, what is left](https://git.torb.dev/torbscript/language/src/commit/393ef2608e4a60b8ff76d8b6b408951b822d887d/docs/design/PROJECT.md#L1337) ## Acceptance criteria - [ ] `torb publish` prints the environment variables the manifest's evaluation read - [ ] The lock's `settings` block records them in `from` - [ ] Documented in `docs/tooling/project-lock-trb.md` ## Dependencies None known. _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). Records evaluation-read variables in the lock from/settings block per PROJECT.md "what is left". Changes the lock format, so a breaking and seed-impact check is due in refine. Release freeze for 0.1.0 (2026-10-06) holds new PRs, next: refine (queued)

[loop:torbscript] intake: in scope (author orion, label loop). Records evaluation-read variables in the lock `from`/settings block per PROJECT.md "what is left". Changes the lock format, so a breaking and seed-impact check is due in refine. Release freeze for 0.1.0 (2026-10-06) holds new PRs, next: refine (queued)
Author
Collaborator

[loop:torbscript] refine: still queued behind the intake order. next: waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z

[loop:torbscript] refine: still queued behind the intake order. next: 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-20261012 until 2026-10-12T15:13Z

[loop:torbscript] claim refine by session:loop-torbscript-20261012 until 2026-10-12T15:13Z
Author
Collaborator

[loop:torbscript] decided by the loop: scope, format and hashing.

Scope: variables only, one PR. The issue title and criteria name variables. file lines of from { } are filed as a separate follow-up (#331) so this stays one commit of compiler code plus one of docs.

Design point: docs/design/PROJECT.md section 8 ("A variable is never recorded by value", the from { } example, and the unset: true paragraph) and section 11 ("What is left": no from section yet). ROADMAP: package manager.

Format (decided):

  • settings "<pkg>" { ... from { variable "NAME", hash: "sha256:<hex>" ; variable "OTHER", unset: true } }, from last inside the block, lines sorted by name, block omitted when the evaluation read nothing (so every literal manifest, including the repository's own, renders exactly as today).
  • The hash is SHA-256 (std/digest, the compiler already uses it for tree hashes) over name + "\n" + value, the same input as the local 64-bit hash of build/manifest-inputs.trb, so two variables with one value do not look alike. The value itself is never written, neither to the lock nor to the publish output.
  • Only variables the evaluation actually asked for, as the sandbox's record grant reports them (recordedInputs); a manifest that is read statically has none. An unset variable is recorded as unset: true.
  • Additive: an older lock without from is read unchanged; readLock reads the block into a new Manifest field (default empty). The registry reads settings from the archive's lock and does not act on from.
  • torb lock writes the block as well (it renders the same settings); torb lock --check is therefore as environment-dependent as the evaluated version already is for a manifest that reads a variable. Documented in the pitfalls of project-lock-trb.md.
  • torb publish prints reads: NAME (set) / reads: NAME (unset) per variable before uploading, one line each, sorted; nothing when none.

Seed impact: none. No syntax change, no new native, no driver flag, no std name looked up by string; compiler/src/vm/manifest.trb, compiler/src/project/manifest.trb, compiler/src/package/lock.trb, compiler/src/cli/packages.trb and docs only.

[loop:torbscript] decided by the loop: scope, format and hashing. **Scope: variables only, one PR.** The issue title and criteria name variables. `file` lines of `from { }` are filed as a separate follow-up (#331) so this stays one commit of compiler code plus one of docs. **Design point:** docs/design/PROJECT.md section 8 ("A variable is never recorded by value", the `from { }` example, and the `unset: true` paragraph) and section 11 ("What is left": no `from` section yet). ROADMAP: package manager. **Format (decided):** - `settings "<pkg>" { ... from { variable "NAME", hash: "sha256:<hex>" ; variable "OTHER", unset: true } }`, `from` last inside the block, lines sorted by name, block omitted when the evaluation read nothing (so every literal manifest, including the repository's own, renders exactly as today). - The hash is SHA-256 (`std/digest`, the compiler already uses it for tree hashes) over `name + "\n" + value`, the same input as the local 64-bit hash of `build/manifest-inputs.trb`, so two variables with one value do not look alike. The value itself is never written, neither to the lock nor to the `publish` output. - Only variables the evaluation actually asked for, as the sandbox's `record` grant reports them (`recordedInputs`); a manifest that is read statically has none. An unset variable is recorded as `unset: true`. - Additive: an older lock without `from` is read unchanged; `readLock` reads the block into a new `Manifest` field (default empty). The registry reads settings from the archive's lock and does not act on `from`. - `torb lock` writes the block as well (it renders the same `settings`); `torb lock --check` is therefore as environment-dependent as the evaluated `version` already is for a manifest that reads a variable. Documented in the pitfalls of project-lock-trb.md. - `torb publish` prints `reads: NAME (set)` / `reads: NAME (unset)` per variable before uploading, one line each, sorted; nothing when none. **Seed impact:** none. No syntax change, no new native, no driver flag, no std name looked up by string; `compiler/src/vm/manifest.trb`, `compiler/src/project/manifest.trb`, `compiler/src/package/lock.trb`, `compiler/src/cli/packages.trb` and docs only.
Author
Collaborator

[loop:torbscript] refine: ready.

Acceptance criteria (replace the issue's list; testable):

  • The evaluation's recorded variables reach the settings: evaluatedManifest (compiler/src/cli/packages.trb) answers the variable names (and set/unset state) the sandbox recorded; a manifest read statically answers none.
  • torb publish of a package whose project.trb reads Environment.get "X" prints one reads: X (set) or reads: X (unset) line per variable, sorted, and never the value (test with a value that must not appear in stdout).
  • torb lock and torb publish write from { variable "X", hash: "sha256:...", ... } as the last part of the package's settings block (unset: true for an unset one); the hash is SHA-256 of name\nvalue; a manifest that read nothing renders byte-identically to today.
  • readLock of a lock with a from block round-trips: renderLock(readLock(text)) == text; a lock without from is read unchanged.
  • Tests in the lock and publish suites for: set variable, unset variable, no variables, round trip, value absent from every output.
  • docs/tooling/project-lock-trb.md (synopsis, parts table, pitfall on environment-dependence of torb lock --check) and torb-publish.md document it; docs/design/PROJECT.md section 11 "What is left" and ROADMAP.md updated (no from section left for variables; files remain); skills/ regenerated.

Size: one PR, two Conventional Commits (feat(package): record the variables a manifest read in the lock + docs(tooling): ...).
Seed impact: none (see decision above). Worker: sonnet/medium is enough only if the touched code stays out of checker/IR/VM internals; it does (package/cli/vm manifest glue), so sonnet/medium.
Dependencies: none open. Follow-up for file lines: filed as #331 (depends on #29).

Token usage of this refine worker: about 85k.

[loop:torbscript] refine: ready. **Acceptance criteria (replace the issue's list; testable):** - [ ] The evaluation's recorded variables reach the settings: `evaluatedManifest` (compiler/src/cli/packages.trb) answers the variable names (and set/unset state) the sandbox recorded; a manifest read statically answers none. - [ ] `torb publish` of a package whose `project.trb` reads `Environment.get "X"` prints one `reads: X (set)` or `reads: X (unset)` line per variable, sorted, and never the value (test with a value that must not appear in stdout). - [ ] `torb lock` and `torb publish` write `from { variable "X", hash: "sha256:...", ... }` as the last part of the package's `settings` block (`unset: true` for an unset one); the hash is SHA-256 of `name\nvalue`; a manifest that read nothing renders byte-identically to today. - [ ] `readLock` of a lock with a `from` block round-trips: `renderLock(readLock(text)) == text`; a lock without `from` is read unchanged. - [ ] Tests in the lock and publish suites for: set variable, unset variable, no variables, round trip, value absent from every output. - [ ] `docs/tooling/project-lock-trb.md` (synopsis, parts table, pitfall on environment-dependence of `torb lock --check`) and `torb-publish.md` document it; `docs/design/PROJECT.md` section 11 "What is left" and `ROADMAP.md` updated (no `from` section left for variables; files remain); `skills/` regenerated. **Size:** one PR, two Conventional Commits (`feat(package): record the variables a manifest read in the lock` + `docs(tooling): ...`). **Seed impact:** none (see decision above). Worker: sonnet/medium is enough only if the touched code stays out of checker/IR/VM internals; it does (package/cli/vm manifest glue), so sonnet/medium. **Dependencies:** none open. Follow-up for `file` lines: filed as #331 (depends on #29). Token usage of this refine worker: about 85k.
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261012 until 2026-10-12T19:16Z

[loop:torbscript] claim implement by session:loop-torbscript-20261012 until 2026-10-12T19:16Z
argus closed this issue 2026-10-12 15:14:13 +00:00
Author
Collaborator

[loop:torbscript] done: PR #337 merged by argus at 2026-10-12T15:14Z, issue closed by the merge. No release or deploy step in the PR; follow-up for file lines of from { } stays #331.

[loop:torbscript] done: PR #337 merged by argus at 2026-10-12T15:14Z, issue closed by the merge. No release or deploy step in the PR; follow-up for `file` lines of `from { }` stays #331.
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#29
No description provided.