@lapxo/bound 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  Declare what must hold. Read what does. Keep the evidence
6
6
 
7
7
  ```bash
8
- npx @lapxo/bound@0.1.7 fold --as help
9
- npx @lapxo/bound@0.1.7 fold
8
+ npx @lapxo/bound@0.1.8 fold --as help
9
+ npx @lapxo/bound@0.1.8 fold
10
10
  ```
11
11
 
12
12
  ## How Bound reads a project
@@ -18,9 +18,9 @@ Bound reads a project's admitted statements and observations through its selecte
18
18
  From a project with an admitted lock and selected views, inspect its standing, ask for its evidence, then verify the committed outputs:
19
19
 
20
20
  ```sh
21
- npx @lapxo/bound@0.1.7 fold --as lines
22
- npx @lapxo/bound@0.1.7 fold --as receipts@1
23
- npx @lapxo/bound@0.1.7 fold --check
21
+ npx @lapxo/bound@0.1.8 fold --as lines
22
+ npx @lapxo/bound@0.1.8 fold --as receipts@1
23
+ npx @lapxo/bound@0.1.8 fold --check
24
24
  ```
25
25
 
26
26
  Use this flow to review a project change or check a dependency's declared contract. `--check` verifies existing evidence; it does not execute a missing reading. A file fold names readings and explicitly says that it computed no encounters.
@@ -66,11 +66,11 @@ lot_dir="$(mktemp -d)"
66
66
  Have the selected view produce a proposal at `$lot_dir/proposal.bound`, or prepare the project's permitted lines there for review. Unsigned proposals use `by=target`, without a preassigned epoch or `sig`. Lots stay outside the repository; the committed bound files are only `TARGET.bound` and `receipts.bound`.
67
67
 
68
68
  ```sh
69
- npx @lapxo/bound@0.1.7 sign "$lot_dir/proposal.bound" \
69
+ npx @lapxo/bound@0.1.8 sign "$lot_dir/proposal.bound" \
70
70
  --key "$BOUND_KEY_ID" --key-file "$BOUND_KEY_FILE" \
71
71
  > "$lot_dir/signed.bound" &&
72
- npx @lapxo/bound@0.1.7 land "$lot_dir/signed.bound" &&
73
- npx @lapxo/bound@0.1.7 fold
72
+ npx @lapxo/bound@0.1.8 land "$lot_dir/signed.bound" &&
73
+ npx @lapxo/bound@0.1.8 fold
74
74
  ```
75
75
 
76
76
  `sign` assigns the admitted epoch and writes the signed lot to stdout. `land` validates the whole lot before admission. A refusal is evidence to inspect; it is not success. Do not proceed after a failed signature or admission. The key file is a PKCS8 private key matching the admitted public key; do not put it in the lot, source tree, package or CI artifacts.
package/TARGET.bound CHANGED
@@ -1,4 +1,4 @@
1
- bound-lock/1 about="# @lapxo/bound\n\n## Use Bound in a project\n\nFrom a project with an admitted lock and selected views, inspect its standing, ask for its evidence, then verify the committed outputs:\n\n```sh\nnpx @lapxo/bound@0.1.7 fold --as lines\nnpx @lapxo/bound@0.1.7 fold --as receipts@1\nnpx @lapxo/bound@0.1.7 fold --check\n```\n\nUse this flow to review a project change or check a dependency's declared contract. `--check` verifies existing evidence; it does not execute a missing reading. A file fold names readings and explicitly says that it computed no encounters.\n\nIndependent observations are judged through the declared typed cells view. The selected topos supplies the form, origin evidence and bounds. Bound keeps attribution and exact-ID withdrawals through the fold.\n\nA selected form can instead describe a set of artifacts, a delivery interval or another domain's values. The project declares the form, origin evidence and views; Bound does not infer them from filenames or units.\n\n\nDeclare what must hold. Read what does. Keep the evidence.\n\nBound reads a project's admitted statements, checks observations against its requirements, and produces the views its selected topos declares. It keeps conflicting evidence and its origins instead of choosing a convenient answer.\n\n`fold` reads. `sign` signs a proposed lot. `land` admits that lot under the place's authority. These acts work across domains: a selected topos supplies forms, units, readers and views.\n\n## Start in an admitted project\n\n```sh\nnpx @lapxo/bound@0.1.7 fold --as help\nnpx @lapxo/bound@0.1.7 fold\n```\n\nThe help view prints:\n\n```text\nverbs fold land sign\nflags --as --check --key --key-file --signer --place\n```\n\nThe default fold runs the project's declared views. Its authority and selected topos determine what can be admitted, read and shown.\n\nStart with the team's accepted TARGET, admitted authority and selected readers. [Full usage guide](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md).\n\n## A meeting everyone can understand\n\nAna is available from 10 to 14, Luis from 12 to 16, and the room from 10 to 13. Their common availability is 12 to 13. A boss available from 18 to 20 makes the encounter incompatible. Withdrawing that exact reading restores the overlap; Ana, Luis and the room remain.\n\nWith an interval form, those are object operations: observe independent claims, meet them, withdraw by id, and read the state. A narrower compatible meet is not a fork. Folding a file of declarations alone does not calculate meeting availability.\n\nThe same pattern applies to a delivery window, a sensor's allowed range, or an agreed performance budget. The chosen topos determines the units and how evidence is obtained. Bound does not supply a meeting-specific rule.\n\n## See how information holds together\n\n![Cells, travelling bounds and a local join](https://raw.githubusercontent.com/Lapxo/bound/2053bb6d6188f04538114eae6a0add5166944ed3/docs/readme-assets/atlas.svg)\n\nA travelling ceiling on B reaches C and G through their declared rest. A local join widens B alone. D is independent. The figure shows those relations; point size and camera distance do not measure information.\n\n| State | Meaning |\n| --- | --- |\n| REQUIRED | Compatible bounds, fewer than two independent origins. |\n| FREE | Independent origins meet and their encounter fits the bounds. |\n| CONFLICT | Bounds conflict, or eligible claims have no common encounter. |\n| FORBIDDEN | An inhabited encounter does not fit the bounds. |\n\nBounds are checked before origins and claims. A receipt is evidence of a reading, not another origin. Duplicating one does not add freedom.\n\n## Change a project without erasing evidence\n\nWork in the project's directory. Use an existing admitted key identifier and its matching private key stored outside every repository. The admitted key also names its signer with `keys/<who> measure=signer value=file`; `signer/timeout` and `signer/response-bytes` declare its limits. Your public key and coverage belong to the authority contract; possession of a private key alone does not authorize a scope.\n\n```sh\nexport BOUND_KEY_ID='your-admitted-key-id'\nexport BOUND_KEY_FILE=\"$HOME/Private/keys/your-device.pem\"\nlot_dir=\"$(mktemp -d)\"\n```\n\nHave the selected view produce a proposal at `$lot_dir/proposal.bound`, or prepare the project's permitted lines there for review. Unsigned proposals use `by=target`, without a preassigned epoch or `sig`. Lots stay outside the repository; the committed bound files are only `TARGET.bound` and `receipts.bound`.\n\n```sh\nnpx @lapxo/bound@0.1.7 sign \"$lot_dir/proposal.bound\" \\\n --key \"$BOUND_KEY_ID\" --key-file \"$BOUND_KEY_FILE\" \\\n > \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.7 land \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.7 fold\n```\n\n`sign` assigns the admitted epoch and writes the signed lot to stdout. `land` validates the whole lot before admission. A refusal is evidence to inspect; it is not success. Do not proceed after a failed signature or admission. The key file is a PKCS8 private key matching the admitted public key; do not put it in the lot, source tree, package or CI artifacts.\n\nFor typed object withdrawals, `takes` names the exact claim or mark id. Removing a local join leaves the travelling sign live. For untyped configuration, use the wire's exact withdrawal selectors; do not combine withdrawal and replacement with identical selectors in one lot. Wire alphabet updates supersede by epoch.\n\n[Authority, withdrawals, receipts and PR review](docs/usage.md).\n\n## Read a declared view and reuse its evidence\n\nWhen the project has admitted a cells view:\n\n```sh\nnpx @lapxo/bound@0.1.7 fold --as cells\n```\n\nThe installed interval scene printed this on an unchanged second reading:\n\n```text\nRECEIPTS 4 read · 0 opened · idle · provider 0\n```\n\nNative receipts identify the live semantic inputs, declared rest, selected topos, codecs and selected rendering implementation. They exclude delivery count, display paths and Bound's error wrapper. A local join changes its own cell's receipt. A travelling sign changes dependent cells. Missing or corrupt carried bytes cannot prove reuse.\n\nFor judgement:\n\n```sh\nnpx @lapxo/bound@0.1.7 fold --check\n```\n\nKeep stdout, stderr and the exit status. `--check` is not an install-and-build replacement. A source test passing does not pay an unread ceiling, prove a cold clone, or accept a release.\n\n## Select a topos by what it declares\n\n`sources/<name>` says where a world can be obtained. An admitted `uses/<name>` names the digest of that topos's folded standing: canonical live claims in wire byte order, excluding signature envelopes and host shape. Re-signing the same standing preserves the pin. A changed live form, class, view or offer changes it.\n\n`restsOn` closes artifact bytes separately. A capsule is one offer. Forms, classes and views need no capsule merely to be selected. Runtime and packing do not define standing identity. npm dependency ranges remain package metadata; they are not standing pins.\n\n| Responsibility | Owner |\n| --- | --- |\n| Meet, state, live acts and rest | Obligations |\n| Wire, forms, classes, views and offer contracts | Topos |\n| Admission, folding and evidence | Bound |\n| Domain measurement and representation | Selected topos |\n| Storage, transport and execution | Host |\n\nCell `restsOn` is the object's relation. Directory prefixes and file summaries are host coordinates, not object rest. Wire tokens are protocol constants, not organization, host, path or key literals.\n\n## Repository rules\n\nCommit `TARGET.bound`, `receipts.bound` and the outputs the forge reads. Ignore `.bound/` from the first line of `.gitignore`. Keep proposals, signed lots, keys, ledgers, caches and dependency blobs outside the published tree.\n\nThe lock is the project's own contract and pins. Read a dependency's declarations from its selected standing; do not copy its lines into your lock. README, package metadata and workflows must be renders of admitted declarations. A scan is an observation, not permission to lower a ceiling.\n\nA PR proposes lines and the leaf changes they render. The judge uses the team's accepted contract independently of the proposed revision. Preserve refusals, conflicting origins and unpaid demands. [Repository and contribution rules](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md#repository-and-pr-review).\n\n## An atlas you can question\n\nInformation can share a history without sharing a single presentation. The same admitted cells can support a compact status view, a spatial view of their relations, or a focused reading of one disagreement. Each view asks for a region and resolution; its selected topos determines the representation.\n\nThis makes changes inspectable. A local act can remain local, travelling bounds can reach dependent cells, and a receipt can name the inputs of the reading you saw. You can ask what changed and what depends on it without turning a drawing into the algebra.\n\nA pin names standing, not a download URL or runtime entry. Its declared artifact dependencies close the bytes needed for an offered operation. The boundary lets a form or view remain meaningful even when it has no executable capsule.\n\nUse Bound where independently attributed observations must be judged against an accepted contract: compatibility between components, operational limits, or a team's project requirements. The selected topos must supply the actual measurements; a digest identifies the evidence without declaring it true.\n\n[Contribute a counterexample or a proposed lot](CONTRIBUTING.md).\n\n\n## Foundations and related libraries\n\nThe two-sided constraint object is described in Nahum Ochoa's [Two-Sided Constraints on a Valued Lattice](https://doi.org/10.5281/zenodo.21858428), DOI `10.5281/zenodo.21858428`. Bound uses the object through [Obligations](https://github.com/Lapxo/obligations); [Topos](https://github.com/Lapxo/topos) supplies the wire and contracts for forms, views and selected worlds. Bound admits, folds and retains evidence across those declared boundaries. A digest identifies bytes; it does not certify that an observation is true.\n" at=witness:bound-017-public-boundary by=target form=alphabet measure=text role=writes scope=prose/en/files/public-0 shape=README.md value=lock
1
+ bound-lock/1 about="# @lapxo/bound\n\n## Use Bound in a project\n\nFrom a project with an admitted lock and selected views, inspect its standing, ask for its evidence, then verify the committed outputs:\n\n```sh\nnpx @lapxo/bound@0.1.8 fold --as lines\nnpx @lapxo/bound@0.1.8 fold --as receipts@1\nnpx @lapxo/bound@0.1.8 fold --check\n```\n\nUse this flow to review a project change or check a dependency's declared contract. `--check` verifies existing evidence; it does not execute a missing reading. A file fold names readings and explicitly says that it computed no encounters.\n\nIndependent observations are judged through the declared typed cells view. The selected topos supplies the form, origin evidence and bounds. Bound keeps attribution and exact-ID withdrawals through the fold.\n\nA selected form can instead describe a set of artifacts, a delivery interval or another domain's values. The project declares the form, origin evidence and views; Bound does not infer them from filenames or units.\n\n\nDeclare what must hold. Read what does. Keep the evidence.\n\nBound reads a project's admitted statements, checks observations against its requirements, and produces the views its selected topos declares. It keeps conflicting evidence and its origins instead of choosing a convenient answer.\n\n`fold` reads. `sign` signs a proposed lot. `land` admits that lot under the place's authority. These acts work across domains: a selected topos supplies forms, units, readers and views.\n\n## Start in an admitted project\n\n```sh\nnpx @lapxo/bound@0.1.8 fold --as help\nnpx @lapxo/bound@0.1.8 fold\n```\n\nThe help view prints:\n\n```text\nverbs fold land sign\nflags --as --check --key --key-file --signer --place\n```\n\nThe default fold runs the project's declared views. Its authority and selected topos determine what can be admitted, read and shown.\n\nStart with the team's accepted TARGET, admitted authority and selected readers. [Full usage guide](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md).\n\n## A meeting everyone can understand\n\nAna is available from 10 to 14, Luis from 12 to 16, and the room from 10 to 13. Their common availability is 12 to 13. A boss available from 18 to 20 makes the encounter incompatible. Withdrawing that exact reading restores the overlap; Ana, Luis and the room remain.\n\nWith an interval form, those are object operations: observe independent claims, meet them, withdraw by id, and read the state. A narrower compatible meet is not a fork. Folding a file of declarations alone does not calculate meeting availability.\n\nThe same pattern applies to a delivery window, a sensor's allowed range, or an agreed performance budget. The chosen topos determines the units and how evidence is obtained. Bound does not supply a meeting-specific rule.\n\n## See how information holds together\n\n![Cells, travelling bounds and a local join](https://raw.githubusercontent.com/Lapxo/bound/2053bb6d6188f04538114eae6a0add5166944ed3/docs/readme-assets/atlas.svg)\n\nA travelling ceiling on B reaches C and G through their declared rest. A local join widens B alone. D is independent. The figure shows those relations; point size and camera distance do not measure information.\n\n| State | Meaning |\n| --- | --- |\n| REQUIRED | Compatible bounds, fewer than two independent origins. |\n| FREE | Independent origins meet and their encounter fits the bounds. |\n| CONFLICT | Bounds conflict, or eligible claims have no common encounter. |\n| FORBIDDEN | An inhabited encounter does not fit the bounds. |\n\nBounds are checked before origins and claims. A receipt is evidence of a reading, not another origin. Duplicating one does not add freedom.\n\n## Change a project without erasing evidence\n\nWork in the project's directory. Use an existing admitted key identifier and its matching private key stored outside every repository. The admitted key also names its signer with `keys/<who> measure=signer value=file`; `signer/timeout` and `signer/response-bytes` declare its limits. Your public key and coverage belong to the authority contract; possession of a private key alone does not authorize a scope.\n\n```sh\nexport BOUND_KEY_ID='your-admitted-key-id'\nexport BOUND_KEY_FILE=\"$HOME/Private/keys/your-device.pem\"\nlot_dir=\"$(mktemp -d)\"\n```\n\nHave the selected view produce a proposal at `$lot_dir/proposal.bound`, or prepare the project's permitted lines there for review. Unsigned proposals use `by=target`, without a preassigned epoch or `sig`. Lots stay outside the repository; the committed bound files are only `TARGET.bound` and `receipts.bound`.\n\n```sh\nnpx @lapxo/bound@0.1.8 sign \"$lot_dir/proposal.bound\" \\\n --key \"$BOUND_KEY_ID\" --key-file \"$BOUND_KEY_FILE\" \\\n > \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.8 land \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.8 fold\n```\n\n`sign` assigns the admitted epoch and writes the signed lot to stdout. `land` validates the whole lot before admission. A refusal is evidence to inspect; it is not success. Do not proceed after a failed signature or admission. The key file is a PKCS8 private key matching the admitted public key; do not put it in the lot, source tree, package or CI artifacts.\n\nFor typed object withdrawals, `takes` names the exact claim or mark id. Removing a local join leaves the travelling sign live. For untyped configuration, use the wire's exact withdrawal selectors; do not combine withdrawal and replacement with identical selectors in one lot. Wire alphabet updates supersede by epoch.\n\n[Authority, withdrawals, receipts and PR review](docs/usage.md).\n\n## Read a declared view and reuse its evidence\n\nWhen the project has admitted a cells view:\n\n```sh\nnpx @lapxo/bound@0.1.8 fold --as cells\n```\n\nThe installed interval scene printed this on an unchanged second reading:\n\n```text\nRECEIPTS 4 read · 0 opened · idle · provider 0\n```\n\nNative receipts identify the live semantic inputs, declared rest, selected topos, codecs and selected rendering implementation. They exclude delivery count, display paths and Bound's error wrapper. A local join changes its own cell's receipt. A travelling sign changes dependent cells. Missing or corrupt carried bytes cannot prove reuse.\n\nFor judgement:\n\n```sh\nnpx @lapxo/bound@0.1.8 fold --check\n```\n\nKeep stdout, stderr and the exit status. `--check` is not an install-and-build replacement. A source test passing does not pay an unread ceiling, prove a cold clone, or accept a release.\n\n## Select a topos by what it declares\n\n`sources/<name>` says where a world can be obtained. An admitted `uses/<name>` names the digest of that topos's folded standing: canonical live claims in wire byte order, excluding signature envelopes and host shape. Re-signing the same standing preserves the pin. A changed live form, class, view or offer changes it.\n\n`restsOn` closes artifact bytes separately. A capsule is one offer. Forms, classes and views need no capsule merely to be selected. Runtime and packing do not define standing identity. npm dependency ranges remain package metadata; they are not standing pins.\n\n| Responsibility | Owner |\n| --- | --- |\n| Meet, state, live acts and rest | Obligations |\n| Wire, forms, classes, views and offer contracts | Topos |\n| Admission, folding and evidence | Bound |\n| Domain measurement and representation | Selected topos |\n| Storage, transport and execution | Host |\n\nCell `restsOn` is the object's relation. Directory prefixes and file summaries are host coordinates, not object rest. Wire tokens are protocol constants, not organization, host, path or key literals.\n\n## Repository rules\n\nCommit `TARGET.bound`, `receipts.bound` and the outputs the forge reads. Ignore `.bound/` from the first line of `.gitignore`. Keep proposals, signed lots, keys, ledgers, caches and dependency blobs outside the published tree.\n\nThe lock is the project's own contract and pins. Read a dependency's declarations from its selected standing; do not copy its lines into your lock. README, package metadata and workflows must be renders of admitted declarations. A scan is an observation, not permission to lower a ceiling.\n\nA PR proposes lines and the leaf changes they render. The judge uses the team's accepted contract independently of the proposed revision. Preserve refusals, conflicting origins and unpaid demands. [Repository and contribution rules](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md#repository-and-pr-review).\n\n## An atlas you can question\n\nInformation can share a history without sharing a single presentation. The same admitted cells can support a compact status view, a spatial view of their relations, or a focused reading of one disagreement. Each view asks for a region and resolution; its selected topos determines the representation.\n\nThis makes changes inspectable. A local act can remain local, travelling bounds can reach dependent cells, and a receipt can name the inputs of the reading you saw. You can ask what changed and what depends on it without turning a drawing into the algebra.\n\nA pin names standing, not a download URL or runtime entry. Its declared artifact dependencies close the bytes needed for an offered operation. The boundary lets a form or view remain meaningful even when it has no executable capsule.\n\nUse Bound where independently attributed observations must be judged against an accepted contract: compatibility between components, operational limits, or a team's project requirements. The selected topos must supply the actual measurements; a digest identifies the evidence without declaring it true.\n\n[Contribute a counterexample or a proposed lot](CONTRIBUTING.md).\n\n\n## Foundations and related libraries\n\nThe two-sided constraint object is described in Nahum Ochoa's [Two-Sided Constraints on a Valued Lattice](https://doi.org/10.5281/zenodo.21858428), DOI `10.5281/zenodo.21858428`. Bound uses the object through [Obligations](https://github.com/Lapxo/obligations); [Topos](https://github.com/Lapxo/topos) supplies the wire and contracts for forms, views and selected worlds. Bound admits, folds and retains evidence across those declared boundaries. A digest identifies bytes; it does not certify that an observation is true.\n" at=witness:first-unpaid-judgment-fix-release by=target form=alphabet measure=text role=writes scope=prose/en/files/public-0 shape=README.md value=lock
2
2
  bound-lock/1 about="# Authenticated evidence view\n\nThe declared evidence@8 view projects authenticated delivery history of this place. It preserves signatures and key attribution, including admitted receipts from an attest-class key. Evidence is not normative configuration, proof of truth, or an independent observation origin. Authority and coverage are checked by the existing Topos contract; no consumer or device type changes that boundary.\n\n\nThe no sample specifies an uncovered write and tampered signed bytes. Both must refuse by name. Exact withdrawals remove only covered normative lines; authenticated evidence remains inspectable. The vectors assert status, signature verification and observable CLI output. No private key bytes are printed or shipped.\n\n## Folded standing\n\nA place declares `view/standing role=demands form=alphabet measure=id value=standing`. `fold --as standing` authenticates each local line against its admission snapshot, then applies revisions and covered exact withdrawals through the existing fold. Every declared key class participates, including attest. Committed acts and historical journals have the same public output. Retiring a key does not erase its previously admitted evidence. Replay adds nothing. Foreign history grants no local authority. This projection is distinct from authenticated delivery history and does not create a new authority lock. An undeclared standing view refuses by name.\n" at=witness:bound-017-public-boundary by=target form=alphabet measure=text role=writes scope=prose/en/files/contract-evidence-view shape=docs/contracts/evidence-view.md value=lock
3
3
  bound-lock/1 about="# Contributing to Bound\n\nBring a counterexample, an observation or a proposed lot. Include the inputs and the output that led you to it. A signature establishes who was authorized to speak; it does not make their result true.\n\n## Set up a working copy\n\nClone the repository and use the Node version supported by package.json. If package-lock.json is present, run npm ci; otherwise use npm install --ignore-scripts --no-package-lock. Then run:\n\n```sh\nnpm run build\nnpm test\n```\n\nThese are development checks, not project acceptance. For a place with admitted trust context and native receipts, run the product judgement as well:\n\n```sh\nnpx @lapxo/bound@0.1.0 fold --check\n```\n\nPreserve a refusal and its exit status in your report. Do not borrow a neighbouring checkout's ledger or substitute local bytes for a named pin.\n\n## Make the smallest useful change\n\nBound owns admission, folding and evidence. Topos owns grammar, forms, classes, views and their contracts. A selected topos owns domain measurement. Obligations owns the algebra. Keep each change in its layer; do not put a domain decoder, path-based inference or a fallback for a missing pin into Bound.\n\nAn algebra change needs an independent oracle and a counterexample. A host change needs evidence for authentic bytes, failure propagation or reuse. A view change needs its declared region and implementation identity. A test should fail for a plausible incorrect implementation, not assert a source string or repeat the same expression on both sides.\n\nKeep regressions for changed signatures, unauthorized coverage, exact-id withdrawal, conflicting evidence, local versus travelling acts, corrupt content and duplicate delivery. Consolidate repeated setup and duplicate scenarios without removing distinct falsifiers.\n\n## Propose and admit\n\nKeep proposal and signed-lot files outside the repository. Use the current admitted wire, by=target, and no preassigned epoch or signature. The team's admitted key signs the lot; Bound admits it under scope coverage. The [usage guide](docs/usage.md) explains the transaction and external key-file requirements.\n\nSend the proposed lines with the leaf changes they render. A hand-edited render is evidence of the intended change, not an admitted contribution. Do not edit the accepted TARGET to make a test or ceiling pass. If a render disagrees with the lock, fix the proposed lines and re-render it.\n\nCommit only the project's TARGET.bound and native receipts.bound as bound files. The first .gitignore line excludes .bound/. Do not commit keys, stores, ledgers, caches, capsules, archives or vendored dependencies.\n\n## Submit a pull request\n\nExplain the concrete behavior before and after the change, the affected layer, and the checks you ran. Include stdout, stderr and exit status for a CLI case. State which reader and input bytes produced the evidence; a source harness is not an installed-package proof.\n\nPolicy changes receive explicit team review separately from measurements of the proposed source. Keep incompatible readings and their origins visible. Never remove a failing test or weaken a ceiling to obtain acceptance. Withdraw statements through their admitted history; do not rewrite prior signatures, tags or releases.\n\nDocumentation and workflows follow the same review: propose their lines and include the rendered changes.\n" at=policy:public-prose by=target form=alphabet measure=text role=writes scope=prose/en/files/public-1 shape=CONTRIBUTING.md value=lock
4
4
  bound-lock/1 about="# Exact release artifact\n\nPacking is a host operation. An archive digest names those archive bytes; it is not the identity of a Topos standing. The release pipeline makes one archive and transfers that same file to its destinations. Repeating a pack operation is not a proof of identical bytes.\n\nThe archive conformance vector declares the host package command, digest algorithm, execution deadline, response bound and its sample packages. It packs each sample once, hashes the resulting bytes, verifies both destination copies, installs offline without package scripts and compares every listed installed member with the input bytes. It executes the installed entry and checks its declared output. Changed archive bytes refuse by digest before they can be treated as the named artifact. The negative control fails when that verification is removed.\n\nThe samples use independent packages with different contents. Their outputs and member digests are captured by the executable vector; their file presence alone is not evidence. The selected publication reader measures this quartet through the existing process contract, and native receipts supply its member status to the plan.\n\nThis is conformance of the packaging recipe. Acceptance of a particular Bound candidate additionally requires the exact archive audit, clean installation and product CLI captures for that archive. A previous archive's captures cannot certify changed implementation bytes. The final candidate must be rebuilt after admitted metadata changes, with every changed member accounted for. The product witness uses the installed reader directly, without a checkout ledger or source conditions.\n\nRendering and installation are different boundaries. README, the manifest and the standard MIT text remain native renders. Publication to a registry or forge is a later owner action; this vector does not publish, authenticate to an account, create a tag or infer an external release from a local file.\n" at=witness:public-contracts-by-operation by=target form=alphabet measure=text role=writes scope=prose/en/files/contract-archive shape=docs/contracts/archive.md value=lock
@@ -25,7 +25,7 @@ bound-lock/1 about="A sequence of declared readings is not an indivisible act. P
25
25
  bound-lock/1 about="Algebraic vacuity, absence of observations and lack of recent activity are separate facts. A view may expose inactivity over an admitted window, but cannot rename it algebraic vacuity or read missing history as zero." at=policy:bound/015-plan by=target form=alphabet measure=text role=writes scope=rationale/015/02 value=lock
26
26
  bound-lock/1 about="Bind a package release with the pipeline views. Bind a page to its receipts with view/readme. Refuse a dependency drift with dep pins. Ask a second head that must agree." at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/learn value=present
27
27
  bound-lock/1 about="Bound is the application of that algebra: signed bounds, folded by one meet, refused when they fork." at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/paper value=present
28
- bound-lock/1 about="Bound reads a project's admitted statements and observations through its selected Topos, then renders the declared views and records their inputs in receipts. The example below explains the object; a file-fold alone does not calculate its intervals.\n\n## Use Bound in a project\n\nFrom a project with an admitted lock and selected views, inspect its standing, ask for its evidence, then verify the committed outputs:\n\n```sh\nnpx @lapxo/bound@0.1.7 fold --as lines\nnpx @lapxo/bound@0.1.7 fold --as receipts@1\nnpx @lapxo/bound@0.1.7 fold --check\n```\n\nUse this flow to review a project change or check a dependency's declared contract. `--check` verifies existing evidence; it does not execute a missing reading. A file fold names readings and explicitly says that it computed no encounters.\n\nIndependent observations are judged through the declared typed cells view. The selected topos supplies the form, origin evidence and bounds. Bound keeps attribution and exact-ID withdrawals through the fold.\n\nA selected form can instead describe a set of artifacts, a delivery interval or another domain's values. The project declares the form, origin evidence and views; Bound does not infer them from filenames or units.\n\n\n## A meeting everyone can understand\n\nAna is available from 10 to 14, Luis from 12 to 16, and the room from 10 to 13. Their common availability is 12 to 13. A boss available from 18 to 20 makes the encounter incompatible. Withdrawing that exact reading restores the overlap; Ana, Luis and the room remain.\n\nWith an interval form, those are object operations: observe independent claims, meet them, withdraw by id, and read the state. A narrower compatible meet is not a fork. Folding a file of declarations alone does not calculate meeting availability.\n\nThe same pattern applies to a delivery window, a sensor's allowed range, or an agreed performance budget. The chosen topos determines the units and how evidence is obtained. Bound does not supply a meeting-specific rule.\n\n## See how information holds together\n\n![Cells, travelling bounds and a local join](https://raw.githubusercontent.com/Lapxo/bound/2053bb6d6188f04538114eae6a0add5166944ed3/docs/readme-assets/atlas.svg)\n\nA travelling ceiling on B reaches C and G through their declared rest. A local join widens B alone. D is independent. The figure shows those relations; point size and camera distance do not measure information.\n\n| State | Meaning |\n| --- | --- |\n| REQUIRED | Compatible bounds, fewer than two independent origins. |\n| FREE | Independent origins meet and their encounter fits the bounds. |\n| CONFLICT | Bounds conflict, or eligible claims have no common encounter. |\n| FORBIDDEN | An inhabited encounter does not fit the bounds. |\n\nBounds are checked before origins and claims. A receipt is evidence of a reading, not another origin. Duplicating one does not add freedom.\n\n## Change a project without erasing evidence\n\nWork in the project's directory. Use an existing admitted key identifier and its matching private key stored outside every repository. The admitted key also names its signer with `keys/<who> measure=signer value=file`; `signer/timeout` and `signer/response-bytes` declare its limits. Your public key and coverage belong to the authority contract; possession of a private key alone does not authorize a scope.\n\n```sh\nexport BOUND_KEY_ID='your-admitted-key-id'\nexport BOUND_KEY_FILE=\"$HOME/Private/keys/your-device.pem\"\nlot_dir=\"$(mktemp -d)\"\n```\n\nHave the selected view produce a proposal at `$lot_dir/proposal.bound`, or prepare the project's permitted lines there for review. Unsigned proposals use `by=target`, without a preassigned epoch or `sig`. Lots stay outside the repository; the committed bound files are only `TARGET.bound` and `receipts.bound`.\n\n```sh\nnpx @lapxo/bound@0.1.7 sign \"$lot_dir/proposal.bound\" \\\n --key \"$BOUND_KEY_ID\" --key-file \"$BOUND_KEY_FILE\" \\\n > \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.7 land \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.7 fold\n```\n\n`sign` assigns the admitted epoch and writes the signed lot to stdout. `land` validates the whole lot before admission. A refusal is evidence to inspect; it is not success. Do not proceed after a failed signature or admission. The key file is a PKCS8 private key matching the admitted public key; do not put it in the lot, source tree, package or CI artifacts.\n\nFor typed object withdrawals, `takes` names the exact claim or mark id. Removing a local join leaves the travelling sign live. For untyped configuration, use the wire's exact withdrawal selectors; do not combine withdrawal and replacement with identical selectors in one lot. Wire alphabet updates supersede by epoch.\n\n[Authority, withdrawals, receipts and PR review](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md).\n\n## Select a topos by what it declares\n\n`sources/<name>` says where a world can be obtained. An admitted `uses/<name>` names the digest of that topos's folded standing: canonical live claims in wire byte order, excluding signature envelopes and host shape. Re-signing the same standing preserves the pin. A changed live form, class, view or offer changes it.\n\n`restsOn` closes artifact bytes separately. A capsule is one offer. Forms, classes and views need no capsule merely to be selected. Runtime and packing do not define standing identity. npm dependency ranges remain package metadata; they are not standing pins.\n\n| Responsibility | Owner |\n| --- | --- |\n| Meet, state, live acts and rest | Obligations |\n| Wire, forms, classes, views and offer contracts | Topos |\n| Admission, folding and evidence | Bound |\n| Domain measurement and representation | Selected topos |\n| Storage, transport and execution | Host |\n\nCell `restsOn` is the object's relation. Directory prefixes and file summaries are host coordinates, not object rest. Wire tokens are protocol constants, not organization, host, path or key literals.\n\n## Repository rules\n\nCommit `TARGET.bound`, `receipts.bound` and the outputs the forge reads. Ignore `.bound/` from the first line of `.gitignore`. Keep proposals, signed lots, keys, ledgers, caches and dependency blobs outside the published tree.\n\nThe lock is the project's own contract and pins. Read a dependency's declarations from its selected standing; do not copy its lines into your lock. README, package metadata and workflows must be renders of admitted declarations. A scan is an observation, not permission to lower a ceiling.\n\nA PR proposes lines and the leaf changes they render. The judge uses the team's accepted contract independently of the proposed revision. Preserve refusals, conflicting origins and unpaid demands. [Repository and contribution rules](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md#repository-and-pr-review).\n\n## An atlas you can question\n\nInformation can share a history without sharing a single presentation. The same admitted cells can support a compact status view, a spatial view of their relations, or a focused reading of one disagreement. Each view asks for a region and resolution; its selected topos determines the representation.\n\nThis makes changes inspectable. A local act can remain local, travelling bounds can reach dependent cells, and a receipt can name the inputs of the reading you saw. You can ask what changed and what depends on it without turning a drawing into the algebra.\n\nA pin names standing, not a download URL or runtime entry. Its declared artifact dependencies close the bytes needed for an offered operation. The boundary lets a form or view remain meaningful even when it has no executable capsule.\n\nUse Bound where independently attributed observations must be judged against an accepted contract: compatibility between components, operational limits, or a team's project requirements. The selected topos must supply the actual measurements; a digest identifies the evidence without declaring it true.\n\n[Contribute a counterexample or a proposed lot](CONTRIBUTING.md).\n\n## Foundations and related libraries\n\nThe two-sided constraint object is described in Nahum Ochoa's [Two-Sided Constraints on a Valued Lattice](https://doi.org/10.5281/zenodo.21858428), DOI `10.5281/zenodo.21858428`. Bound uses the object through [Obligations](https://github.com/Lapxo/obligations); [Topos](https://github.com/Lapxo/topos) supplies the wire and contracts for forms, views and selected worlds. Bound admits, folds and retains evidence across those declared boundaries. A digest identifies bytes; it does not certify that an observation is true.\n" at=witness:bound-017-public-boundary by=target form=alphabet measure=text role=writes scope=prose/en/idea value=present
28
+ bound-lock/1 about="Bound reads a project's admitted statements and observations through its selected Topos, then renders the declared views and records their inputs in receipts. The example below explains the object; a file-fold alone does not calculate its intervals.\n\n## Use Bound in a project\n\nFrom a project with an admitted lock and selected views, inspect its standing, ask for its evidence, then verify the committed outputs:\n\n```sh\nnpx @lapxo/bound@0.1.8 fold --as lines\nnpx @lapxo/bound@0.1.8 fold --as receipts@1\nnpx @lapxo/bound@0.1.8 fold --check\n```\n\nUse this flow to review a project change or check a dependency's declared contract. `--check` verifies existing evidence; it does not execute a missing reading. A file fold names readings and explicitly says that it computed no encounters.\n\nIndependent observations are judged through the declared typed cells view. The selected topos supplies the form, origin evidence and bounds. Bound keeps attribution and exact-ID withdrawals through the fold.\n\nA selected form can instead describe a set of artifacts, a delivery interval or another domain's values. The project declares the form, origin evidence and views; Bound does not infer them from filenames or units.\n\n\n## A meeting everyone can understand\n\nAna is available from 10 to 14, Luis from 12 to 16, and the room from 10 to 13. Their common availability is 12 to 13. A boss available from 18 to 20 makes the encounter incompatible. Withdrawing that exact reading restores the overlap; Ana, Luis and the room remain.\n\nWith an interval form, those are object operations: observe independent claims, meet them, withdraw by id, and read the state. A narrower compatible meet is not a fork. Folding a file of declarations alone does not calculate meeting availability.\n\nThe same pattern applies to a delivery window, a sensor's allowed range, or an agreed performance budget. The chosen topos determines the units and how evidence is obtained. Bound does not supply a meeting-specific rule.\n\n## See how information holds together\n\n![Cells, travelling bounds and a local join](https://raw.githubusercontent.com/Lapxo/bound/2053bb6d6188f04538114eae6a0add5166944ed3/docs/readme-assets/atlas.svg)\n\nA travelling ceiling on B reaches C and G through their declared rest. A local join widens B alone. D is independent. The figure shows those relations; point size and camera distance do not measure information.\n\n| State | Meaning |\n| --- | --- |\n| REQUIRED | Compatible bounds, fewer than two independent origins. |\n| FREE | Independent origins meet and their encounter fits the bounds. |\n| CONFLICT | Bounds conflict, or eligible claims have no common encounter. |\n| FORBIDDEN | An inhabited encounter does not fit the bounds. |\n\nBounds are checked before origins and claims. A receipt is evidence of a reading, not another origin. Duplicating one does not add freedom.\n\n## Change a project without erasing evidence\n\nWork in the project's directory. Use an existing admitted key identifier and its matching private key stored outside every repository. The admitted key also names its signer with `keys/<who> measure=signer value=file`; `signer/timeout` and `signer/response-bytes` declare its limits. Your public key and coverage belong to the authority contract; possession of a private key alone does not authorize a scope.\n\n```sh\nexport BOUND_KEY_ID='your-admitted-key-id'\nexport BOUND_KEY_FILE=\"$HOME/Private/keys/your-device.pem\"\nlot_dir=\"$(mktemp -d)\"\n```\n\nHave the selected view produce a proposal at `$lot_dir/proposal.bound`, or prepare the project's permitted lines there for review. Unsigned proposals use `by=target`, without a preassigned epoch or `sig`. Lots stay outside the repository; the committed bound files are only `TARGET.bound` and `receipts.bound`.\n\n```sh\nnpx @lapxo/bound@0.1.8 sign \"$lot_dir/proposal.bound\" \\\n --key \"$BOUND_KEY_ID\" --key-file \"$BOUND_KEY_FILE\" \\\n > \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.8 land \"$lot_dir/signed.bound\" &&\nnpx @lapxo/bound@0.1.8 fold\n```\n\n`sign` assigns the admitted epoch and writes the signed lot to stdout. `land` validates the whole lot before admission. A refusal is evidence to inspect; it is not success. Do not proceed after a failed signature or admission. The key file is a PKCS8 private key matching the admitted public key; do not put it in the lot, source tree, package or CI artifacts.\n\nFor typed object withdrawals, `takes` names the exact claim or mark id. Removing a local join leaves the travelling sign live. For untyped configuration, use the wire's exact withdrawal selectors; do not combine withdrawal and replacement with identical selectors in one lot. Wire alphabet updates supersede by epoch.\n\n[Authority, withdrawals, receipts and PR review](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md).\n\n## Select a topos by what it declares\n\n`sources/<name>` says where a world can be obtained. An admitted `uses/<name>` names the digest of that topos's folded standing: canonical live claims in wire byte order, excluding signature envelopes and host shape. Re-signing the same standing preserves the pin. A changed live form, class, view or offer changes it.\n\n`restsOn` closes artifact bytes separately. A capsule is one offer. Forms, classes and views need no capsule merely to be selected. Runtime and packing do not define standing identity. npm dependency ranges remain package metadata; they are not standing pins.\n\n| Responsibility | Owner |\n| --- | --- |\n| Meet, state, live acts and rest | Obligations |\n| Wire, forms, classes, views and offer contracts | Topos |\n| Admission, folding and evidence | Bound |\n| Domain measurement and representation | Selected topos |\n| Storage, transport and execution | Host |\n\nCell `restsOn` is the object's relation. Directory prefixes and file summaries are host coordinates, not object rest. Wire tokens are protocol constants, not organization, host, path or key literals.\n\n## Repository rules\n\nCommit `TARGET.bound`, `receipts.bound` and the outputs the forge reads. Ignore `.bound/` from the first line of `.gitignore`. Keep proposals, signed lots, keys, ledgers, caches and dependency blobs outside the published tree.\n\nThe lock is the project's own contract and pins. Read a dependency's declarations from its selected standing; do not copy its lines into your lock. README, package metadata and workflows must be renders of admitted declarations. A scan is an observation, not permission to lower a ceiling.\n\nA PR proposes lines and the leaf changes they render. The judge uses the team's accepted contract independently of the proposed revision. Preserve refusals, conflicting origins and unpaid demands. [Repository and contribution rules](https://github.com/Lapxo/bound/blob/2053bb6d6188f04538114eae6a0add5166944ed3/docs/usage.md#repository-and-pr-review).\n\n## An atlas you can question\n\nInformation can share a history without sharing a single presentation. The same admitted cells can support a compact status view, a spatial view of their relations, or a focused reading of one disagreement. Each view asks for a region and resolution; its selected topos determines the representation.\n\nThis makes changes inspectable. A local act can remain local, travelling bounds can reach dependent cells, and a receipt can name the inputs of the reading you saw. You can ask what changed and what depends on it without turning a drawing into the algebra.\n\nA pin names standing, not a download URL or runtime entry. Its declared artifact dependencies close the bytes needed for an offered operation. The boundary lets a form or view remain meaningful even when it has no executable capsule.\n\nUse Bound where independently attributed observations must be judged against an accepted contract: compatibility between components, operational limits, or a team's project requirements. The selected topos must supply the actual measurements; a digest identifies the evidence without declaring it true.\n\n[Contribute a counterexample or a proposed lot](CONTRIBUTING.md).\n\n## Foundations and related libraries\n\nThe two-sided constraint object is described in Nahum Ochoa's [Two-Sided Constraints on a Valued Lattice](https://doi.org/10.5281/zenodo.21858428), DOI `10.5281/zenodo.21858428`. Bound uses the object through [Obligations](https://github.com/Lapxo/obligations); [Topos](https://github.com/Lapxo/topos) supplies the wire and contracts for forms, views and selected worlds. Bound admits, folds and retains evidence across those declared boundaries. A digest identifies bytes; it does not certify that an observation is true.\n" at=witness:first-unpaid-judgment-fix-release by=target form=alphabet measure=text role=writes scope=prose/en/idea value=present
29
29
  bound-lock/1 about="Cite it as {name}." at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/cff/name value=lock
30
30
  bound-lock/1 about="Cite it by the paper it rests on, Two-Sided Constraints on a Valued Lattice." at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/cff/paper value=lock
31
31
  bound-lock/1 about="Conflicting live wire declarations refuse by scope; no vacuous alphabet." at=policy:bound/015-plan by=target form=alphabet measure=status needs=docs/contracts/wire/unique-live-alphabet.md|samples/yes/wire/unique-live-alphabet.json|vectors/wire/unique-live-alphabet.json|samples/no/wire/unique-live-alphabet.json role=demands scope=wire/unique-live-alphabet value=present
@@ -161,10 +161,10 @@ bound-lock/1 about="handed {input}, it refuses: {why}" at=policy:bound/010-figur
161
161
  bound-lock/1 about="how many axioms the door spells" at=policy:bound/010-samples by=target form=alphabet measure=id role=writes scope=docs/what-holds value=9
162
162
  bound-lock/1 about="how this place is cited" at=policy:bound/010 by=target form=alphabet measure=id needs=CITATION.cff role=demands scope=view/citation-file shape=CITATION.cff value=cff
163
163
  bound-lock/1 about="lines, not a page: blobs, laid snapshots and answer caches no alias, pin or receipt names; land withdraws them" at=policy:bound/views by=target form=alphabet measure=id role=demands scope=view/unnamed value=unnamed
164
- bound-lock/1 about="name: release\non:\n release:\n types: [published]\njobs:\n stage:\n environment: release\n runs-on: ubuntu-latest\n permissions:\n contents: read\n id-token: write\n steps:\n - uses: actions/checkout@v4\n with:\n ref: ${{ github.event.release.tag_name }}\n - uses: actions/setup-node@v4\n with:\n node-version: 24\n - run: npm ci --ignore-scripts\n - run: npm run build\n - run: npm install --global npm@'12.1.0' --ignore-scripts\n - name: Read owner approval\n env:\n GH_TOKEN: ${{ github.token }}\n TAG: ${{ github.event.release.tag_name }}\n run: |\n set -euo pipefail\n mkdir .release\n gh release download \"$TAG\" --pattern approval-signed --dir .release\n node dist/cli/verb.js fold --as release .release/approval-signed > .release/verdict\n cat .release/verdict\n - name: Stage the approved release archive\n env:\n GH_TOKEN: ${{ github.token }}\n TAG: ${{ github.event.release.tag_name }}\n run: |\n set -euo pipefail\n read -r status digest archive source extra < .release/verdict\n test \"$status\" = READY\n test -z \"$extra\"\n gh release download \"$TAG\" --pattern \"$archive\" --dir .release\n printf '%s %s\\n' \"${digest#sha256:}\" \".release/$archive\" | sha256sum -c -\n expected=\"$(node -p \"require('./package.json').name+'@'+require('./package.json').version\")\"\n actual=\"$(tar -xOf \".release/$archive\" package/package.json | node -p \"const p=JSON.parse(require('fs').readFileSync(0,'utf8'));p.name+'@'+p.version\")\"\n test \"$actual\" = \"$expected\"\n printf 'SOURCE release/%s/%s · %s · declared %s\\n' \"$TAG\" \"$archive\" \"$digest\" \"$source\"\n npm stage publish \".release/$archive\" --access public --ignore-scripts\n printf 'STAGED %s · %s · owner approval pending\\n' \"$actual\" \"$digest\"\n" at=witness:bound-017-approved-archive-delivery by=target form=alphabet measure=text role=writes scope=prose/en/files/workflow/release shape=.github/workflows/release.yml value=lock
164
+ bound-lock/1 about="name: release\non:\n workflow_run:\n workflows: [tag]\n types: [completed]\n workflow_dispatch:\njobs:\n stage:\n if: github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'main')\n concurrency: release-delivery\n environment: release\n runs-on: ubuntu-latest\n permissions:\n contents: write\n id-token: write\n steps:\n - uses: actions/checkout@v4\n with:\n ref: ${{ github.event.workflow_run.head_sha || github.sha }}\n - uses: actions/setup-node@v4\n with:\n node-version: 24\n - run: npm ci --ignore-scripts\n - run: npm run build\n - run: npm install --global npm@'12.1.0' --ignore-scripts\n - name: Prepare release\n env:\n GH_TOKEN: ${{ github.token }}\n run: |\n set -euo pipefail\n TAG=\"v$(node -p \"require('./package.json').version\")\"\n printf 'TAG=%s\\n' \"$TAG\" >> \"$GITHUB_ENV\"\n git fetch origin \"refs/tags/$TAG:refs/tags/$TAG\"\n gh api --paginate \"repos/$GITHUB_REPOSITORY/releases\" --jq '.[].tag_name' > \"$RUNNER_TEMP/release-tags\"\n if grep -Fxq \"$TAG\" \"$RUNNER_TEMP/release-tags\"; then\n printf 'RELEASE %s · exists\\n' \"$TAG\"\n else\n gh release create \"$TAG\" --verify-tag --draft --title \"$TAG\" --generate-notes\n printf 'RELEASE %s · draft created · awaiting signed assets\\n' \"$TAG\"\n fi\n - name: Read owner approval\n env:\n GH_TOKEN: ${{ github.token }}\n run: |\n set -euo pipefail\n mkdir .release\n gh release download \"$TAG\" --pattern approval-signed --dir .release\n node dist/cli/verb.js fold --as release .release/approval-signed > .release/verdict\n cat .release/verdict\n - name: Stage the approved release archive\n env:\n GH_TOKEN: ${{ github.token }}\n run: |\n set -euo pipefail\n read -r status digest archive source extra < .release/verdict\n test \"$status\" = READY\n test -z \"$extra\"\n gh release download \"$TAG\" --pattern \"$archive\" --dir .release\n printf '%s %s\\n' \"${digest#sha256:}\" \".release/$archive\" | sha256sum -c -\n expected=\"$(node -p \"require('./package.json').name+'@'+require('./package.json').version\")\"\n actual=\"$(tar -xOf \".release/$archive\" package/package.json | node -p \"const p=JSON.parse(require('fs').readFileSync(0,'utf8'));p.name+'@'+p.version\")\"\n test \"$actual\" = \"$expected\"\n printf 'SOURCE release/%s/%s · %s · declared %s\\n' \"$TAG\" \"$archive\" \"$digest\" \"$source\"\n gh release edit \"$TAG\" --draft=false\n printf 'RELEASE %s · published · %s\\n' \"$TAG\" \"$digest\"\n npm stage publish \".release/$archive\" --access public --ignore-scripts\n printf 'STAGED %s · %s · owner approval pending\\n' \"$actual\" \"$digest\"\n" at=witness:bound-017-automatic-approved-delivery by=target form=alphabet measure=text role=writes scope=prose/en/files/workflow/release shape=.github/workflows/release.yml value=lock
165
165
  bound-lock/1 about="name: tag\non:\n workflow_run:\n workflows: [test]\n types: [completed]\njobs:\n tag:\n if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && github.event.workflow_run.head_branch == 'main'\n runs-on: ubuntu-latest\n permissions:\n contents: write\n steps:\n - uses: actions/checkout@v4\n with:\n ref: ${{ github.event.workflow_run.head_sha }}\n fetch-depth: 0\n - run: |\n version=\"v$(node -p \"require('./package.json').version\")\"\n git tag --list \"$version\" | grep -q . && exit 0\n git tag \"$version\" && git push origin \"$version\"\n" at=policy:bound/pipeline by=target form=alphabet measure=text role=writes scope=prose/en/files/workflow/tag shape=.github/workflows/tag.yml value=lock
166
166
  bound-lock/1 about="name: test\non:\n push:\n branches: [main]\n pull_request:\njobs:\n test:\n strategy:\n fail-fast: false\n matrix:\n node: [22, 24]\n runs-on: ubuntu-latest\n permissions:\n contents: read\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${{ matrix.node }}\n - run: npm ci\n - run: npm run build\n - run: npm test\n - name: Verify native closure and receipt reuse\n run: |\n node dist/cli/verb.js fold --check > \"$RUNNER_TEMP/bound-check.log\" 2>&1 || { cat \"$RUNNER_TEMP/bound-check.log\"; exit 1; }\n cat \"$RUNNER_TEMP/bound-check.log\"\n grep -Eq '^PASS +closed' \"$RUNNER_TEMP/bound-check.log\"\n grep -Eq '^RECEIPTS [1-9][0-9]* read · 0 opened' \"$RUNNER_TEMP/bound-check.log\"\n - run: npm pack --silent\n" at=policy:bound/pipeline by=target form=alphabet measure=text role=writes scope=prose/en/files/workflow/test shape=.github/workflows/test.yml value=lock
167
- bound-lock/1 about="npx @lapxo/bound@0.1.7 fold --as help\nnpx @lapxo/bound@0.1.7 fold" at=witness:bound-017-public-boundary by=target form=alphabet measure=text role=writes scope=prose/en/commands value=lock
167
+ bound-lock/1 about="npx @lapxo/bound@0.1.8 fold --as help\nnpx @lapxo/bound@0.1.8 fold" at=witness:first-unpaid-judgment-fix-release by=target form=alphabet measure=text role=writes scope=prose/en/commands value=lock
168
168
  bound-lock/1 about="obligations is the meet. topos is the line. Worlds outside bound read a calendar, a package, a page. Bound reads lines, folds them, lands what was signed, and signs." at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/rests/on value=present
169
169
  bound-lock/1 about="one origin is REQUIRED, two that meet inside every bound are FREE, two that meet outside a bound are FORBIDDEN, and two that do not meet are CONFLICT" at=policy:bound/010-states by=target form=alphabet measure=id role=writes scope=notation/states value="one origin=REQUIRED|claims that meet and fit the bounds=FREE|claims that meet outside the bounds=FORBIDDEN|bounds that cross=CONFLICT"
170
170
  bound-lock/1 about="take the package in" at=policy:bound/door by=target form=alphabet measure=id role=writes scope=install value=npx
@@ -297,7 +297,7 @@ bound-lock/1 about="the typescript tree world after its released capsule: said,
297
297
  bound-lock/1 about="the vectors a place holds, a row per region, as the fold counts them from its receipts" at=policy:bound/regions by=target form=alphabet measure=receipts role=reads scope=region/vectors value=vector/**
298
298
  bound-lock/1 about="the vectors world saying its own description in its own lock: the regions of 2fb13c6f unchanged, its prose under its key; packed from releases only, topos 0.1.2 and the algebra release, each laid from its digest" at=policy:bound/capsules by=target form=alphabet measure=id role=writes scope=dep/topos-json/own-what shape=dist/index.js value=sha256:5ec73255e3f089e3b9c7bc1d6351a07b8aa302a346fe16ed44cbcb67293c7891
299
299
  bound-lock/1 about="the version the forge tags, read from the manifest" at=policy:bound/pipeline by=target form=alphabet measure=id role=writes scope=pipeline/version value="node -p \"require('./package.json').version\""
300
- bound-lock/1 about="the version this place is bound at" at=witness:bound-017-public-boundary by=target form=alphabet measure=id role=writes scope=version value=0.1.7
300
+ bound-lock/1 about="the version this place is bound at" at=witness:first-unpaid-judgment-fix-release by=target form=alphabet measure=id role=writes scope=version value=0.1.8
301
301
  bound-lock/1 about="the writer that vouches each source at the digest a take judged it: a family the wire lists, which bound reads here and never spells" at=policy:bound/store by=target form=alphabet measure=id role=reads scope=store/vouches value=tree
302
302
  bound-lock/1 about="this place is a package: class defaults of package resolve here" at=policy:bound/place by=target form=alphabet measure=id role=writes scope=place/kind value=package
303
303
  bound-lock/1 about="topos-node with a thin manifest: no typesVersions, main or types, dev dependencies only where a line says so, and a bin field from the place bin/<name> lines" at=policy:bound/capsules by=target form=alphabet measure=id role=writes scope=dep/topos-node/thin-manifest shape=dist/index.js value=sha256:da1fd0bb74f72ae95bce5929055c50ccd150d8903ba5560d99df48bf236d8dc0
@@ -312,7 +312,7 @@ bound-lock/1 about="what the second head found, which leaves the place has writt
312
312
  bound-lock/1 about="when the apart claim is withdrawn" at=policy:bound/door by=target form=alphabet measure=id role=writes scope=form/style/fold/back value=2.2
313
313
  bound-lock/1 about="where a located world keeps each region file, by directory and extension, so the host loads the tree beside the pin" at=policy:bound/010 by=target form=alphabet measure=id role=writes scope=release/layout value=src/regions:.ts
314
314
  bound-lock/1 about="who signs this place" at=policy:bound/010 by=target form=alphabet measure=id role=writes scope=author value=Lapxo
315
- bound-lock/1 about="{\n \"name\": \"@lapxo/bound\",\n \"version\": \"0.1.7\",\n \"type\": \"module\",\n \"description\": \"Read the bounds you already wrote, fold them, and name the contradictions.\",\n \"main\": \"dist/cli/verb.js\",\n \"types\": \"dist/cli/verb.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/cli/verb.d.ts\",\n \"default\": \"./dist/cli/verb.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"scripts\": {\n \"test\": \"node --import ./test/setup.ts --test --test-concurrency=2 test/*.test.ts\",\n \"clean\": \"rm -rf dist .tsbuildinfo* tsconfig.tsbuildinfo\",\n \"build\": \"node tools/build.mjs\",\n \"prepack\": \"npm run build\"\n },\n \"files\": [\n \"LICENSE\",\n \"README.md\",\n \"CONTRIBUTING.md\",\n \"dist/**/*\",\n \"TARGET.bound\",\n \"receipts.bound\",\n \"docs/usage.md\",\n \"docs/readme-assets/atlas.svg\",\n \"docs/contracts/*.md\"\n ],\n \"author\": \"Lapxo\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@lapxo/obligations\": \"0.3.5\",\n \"@lapxo/topos\": \"0.1.13\",\n \"acorn\": \"8.19.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"sideEffects\": false,\n \"engines\": {\n \"node\": \">=22.15\"\n },\n \"bin\": {\n \"bound\": \"./dist/cli/verb.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Lapxo/bound.git\"\n },\n \"homepage\": \"https://github.com/Lapxo/bound#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Lapxo/bound/issues\"\n },\n \"keywords\": [\n \"cli\",\n \"content-addressed\",\n \"provenance\",\n \"receipts\",\n \"constraints\",\n \"reproducible\"\n ]\n}\n" at=witness:bound-017-public-boundary by=target form=alphabet measure=text role=writes scope=prose/en/files/manifest shape=package.json value=lock
315
+ bound-lock/1 about="{\n \"name\": \"@lapxo/bound\",\n \"version\": \"0.1.8\",\n \"type\": \"module\",\n \"description\": \"Read the bounds you already wrote, fold them, and name the contradictions.\",\n \"main\": \"dist/cli/verb.js\",\n \"types\": \"dist/cli/verb.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/cli/verb.d.ts\",\n \"default\": \"./dist/cli/verb.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"scripts\": {\n \"test\": \"node --import ./test/setup.ts --test --test-concurrency=2 test/*.test.ts\",\n \"clean\": \"rm -rf dist .tsbuildinfo* tsconfig.tsbuildinfo\",\n \"build\": \"node tools/build.mjs\",\n \"prepack\": \"npm run build\"\n },\n \"files\": [\n \"LICENSE\",\n \"README.md\",\n \"CONTRIBUTING.md\",\n \"dist/**/*\",\n \"TARGET.bound\",\n \"receipts.bound\",\n \"docs/usage.md\",\n \"docs/readme-assets/atlas.svg\",\n \"docs/contracts/*.md\"\n ],\n \"author\": \"Lapxo\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@lapxo/obligations\": \"0.3.5\",\n \"@lapxo/topos\": \"0.1.13\",\n \"acorn\": \"8.19.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"sideEffects\": false,\n \"engines\": {\n \"node\": \">=22.15\"\n },\n \"bin\": {\n \"bound\": \"./dist/cli/verb.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Lapxo/bound.git\"\n },\n \"homepage\": \"https://github.com/Lapxo/bound#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Lapxo/bound/issues\"\n },\n \"keywords\": [\n \"cli\",\n \"content-addressed\",\n \"provenance\",\n \"receipts\",\n \"constraints\",\n \"reproducible\"\n ]\n}\n" at=witness:first-unpaid-judgment-fix-release by=target form=alphabet measure=text role=writes scope=prose/en/files/manifest shape=package.json value=lock
316
316
  bound-lock/1 about="{\n \"profile\": \"quartet-process@1\",\n \"scope\": \"contract/published\",\n \"surface\": [\n \"contract/published/attest-evidence-view\",\n \"contract/published/cli/fold\",\n \"contract/published/cli/land\",\n \"contract/published/cli/sign\",\n \"contract/published/pipeline/archive\",\n \"contract/published/typed-object-sample\",\n \"contract/published/view/card\",\n \"contract/published/view/citation-file\",\n \"contract/published/view/explanation\",\n \"contract/published/view/guide\",\n \"contract/published/view/help\",\n \"contract/published/view/lines\",\n \"contract/published/view/manifest-render\",\n \"contract/published/view/programs\",\n \"contract/published/view/readme-historical\",\n \"contract/published/view/receipts\",\n \"contract/published/view/reference\",\n \"contract/published/view/release-workflow-render\",\n \"contract/published/view/tsconfig\",\n \"contract/published/view/usage-profile\",\n \"contract/published/view/walk\",\n \"contract/published/view/why\"\n ],\n \"note\": \"Explicit public-surface inventory. A selected coordinate without a descriptor is unpaid. Outstanding capability demands are not advertised implementations.\"\n}" at=witness:exact-archive-conformance by=target form=alphabet measure=text role=writes scope=prose/en/files/publication-inventory shape=docs/contracts/publication.inventory.json value=lock
317
317
  bound-lock/1 about="{count} hold" at=policy:bound/010 by=target form=alphabet measure=text role=writes scope=prose/en/badge/held value=lock
318
318
  bound-lock/1 about="{lo}..{hi} · {state}" at=policy:bound/readme by=target form=alphabet measure=text role=writes scope=prose/en/figure/fold/together value=present
@@ -416,10 +416,10 @@ bound-lock/1 at=policy:selected-wire by=target form=alphabet measure=digest role
416
416
  bound-lock/1 at=witness:bound/014-sdk-source by=target form=alphabet measure=id role=writes scope=sources/topos value=https://registry.npmjs.org/@lapxo/topos/-/topos-0.1.9.tgz
417
417
  bound-lock/1 at=witness:bound/015-hermetic-render-closure by=target form=alphabet measure=digest role=writes scope=uses/rendering value=sha256:c0094dc8c916b3c8ea9df19666816a28230c01808e5d792833c156e8d454a2f0
418
418
  bound-lock/1 at=witness:bound/015-hermetic-render-closure by=target form=alphabet measure=id role=writes scope=dep/topos-doc/born shape=dist/index.js value=sha256:04feef01a8c59cae7ea842198d1faf0091b424129872a847b41c7da0bca6fabf
419
- bound-lock/1 at=witness:current-instrument-cache-guard-is-measured by=target form=alphabet measure=digest role=writes scope=dep/process-readings shape=dist/index.js value=sha256:e71ccc28b4339d58ee6af652f8b20e20b633295e1379eb11c0192812ad72c729
420
- bound-lock/1 at=witness:current-instrument-cache-guard-is-measured by=target form=alphabet measure=digest role=writes scope=dep/source-readings shape=dist/index.js value=sha256:61f0110dd39354687d8f1ed32f281335e3dc0d146ce83dc970db5f7e206f85b8
421
- bound-lock/1 at=witness:current-instrument-cache-guard-is-measured by=target form=alphabet measure=digest role=writes scope=uses/process-readings value=sha256:3de728462d1d1a6d80198528a04f3339e39d54e069d3df3a7448bb4e91c10056
422
- bound-lock/1 at=witness:current-instrument-cache-guard-is-measured by=target form=alphabet measure=digest role=writes scope=uses/source-readings value=sha256:e2d462351bdf13528d761d8b2349170f5ad251c19271d6c2fea5868cdf8337ea
419
+ bound-lock/1 at=witness:first-unpaid-judgment-source-binding by=target form=alphabet measure=digest role=writes scope=dep/source-readings shape=dist/index.js value=sha256:2c3ac505bbf7a63ecc248700bf5003d6a6c6d93bfc0a0a5fafddb939f7cf521d
420
+ bound-lock/1 at=witness:first-unpaid-judgment-source-binding by=target form=alphabet measure=digest role=writes scope=uses/source-readings value=sha256:d94d4e1929079c5d19000f8cc5675a36dcdb85102fc8ddf830649b9d0725a022
421
+ bound-lock/1 at=witness:fixture-dependencies-follow-node-resolution by=target form=alphabet measure=digest role=writes scope=dep/process-readings shape=dist/index.js value=sha256:81f078198f3dcf275e17c1e0c606ad142d8c1ce4d17e44b09537d04bb9d6b351
422
+ bound-lock/1 at=witness:fixture-dependencies-follow-node-resolution by=target form=alphabet measure=digest role=writes scope=uses/process-readings value=sha256:3e11445d3668ced048c661e0ad1c50aa655ea45c7dc383c292dac0465f3c7f7b
423
423
  bound-lock/1 at=witness:process-vectors-held-by-world-and-bound-to-runtime by=target form=alphabet measure=coordinates role=reads scope=region/captures value=dist/**/*.js|TARGET.bound|package.json
424
424
  bound-lock/1 at=witness:process-vectors-held-by-world-and-bound-to-runtime by=target form=alphabet measure=coordinates role=reads scope=region/vectors value=dist/**/*.js|TARGET.bound|package.json
425
425
  bound-lock/1 at=witness:project-coordinates-are-relative by=target form=interval measure=count needs=samples/core/yes/exchange-cost.json|samples/core/no/exchange-cost.json role=reads scope=exchange/cost value=0..0
package/dist/cli/takes.js CHANGED
@@ -3,6 +3,7 @@ import { join } from 'node:path';
3
3
  import { fullDigest } from "../fold/digests.js";
4
4
  import { canonical } from '@lapxo/topos/wire';
5
5
  import { fieldOf, foldClaims } from "../fold/claims.js";
6
+ import { paidOf } from "../fold/paid.js";
6
7
  import { rolesOf } from "../fold/roles.js";
7
8
  import { writerFor } from "../fold/signers.js";
8
9
  import { judgeTake, sealed } from "../judge/take.js";
@@ -46,8 +47,10 @@ export function judgeDemand(root, demand) {
46
47
  for (const [coordinate, digest] of coordinatesOf(root, location, walked))
47
48
  after.set(coordinate, digest);
48
49
  const law = [scope.split('/').pop() ?? scope, fieldOf(demand, 'at').replace(/^witness:/, '')].filter(Boolean);
50
+ const standing = foldClaims(signedOwnerLines(store)).standing;
51
+ const unpaid = paidOf(store, [demand], [], `${wordOf(standing, 'families', 'view')}/`).missing.length === 1;
49
52
  const verdict = judgeTake({
50
- root, scope, value: fieldOf(demand, 'value'), locations, before, after, law,
53
+ root, scope, value: fieldOf(demand, 'value'), locations, before, after, law, unpaid,
51
54
  shape: fieldOf(demand, 'shape'), restsOn: fieldOf(demand, 'restsOn'), witnessOf: (coordinate) => witnessOf(root, coordinate),
52
55
  template: wordOf(foldClaims(signedOwnerLines(store)).standing, 'templates', '{roots}'),
53
56
  });
@@ -90,7 +93,7 @@ export function landTake(root, one, gates) {
90
93
  canonical({
91
94
  scope, role: 'writes', form: 'alphabet', measure: fieldOf(demand, 'measure') || 'status', value: fieldOf(demand, 'value') || 'present', by: 'judge', at: receipt,
92
95
  }),
93
- canonical({ scope, role: 'writes', form: 'alphabet', measure: 'cone', value: verdict.changed.join('|'), by: 'judge', at: receipt }),
96
+ canonical({ scope, role: 'writes', form: 'alphabet', measure: 'cone', value: (verdict.changed.length ? verdict.changed : [...after.keys()].sort()).join('|'), by: 'judge', at: receipt }),
94
97
  ]);
95
98
  }
96
99
  const ms = Date.now() - started;
@@ -45,6 +45,8 @@ export declare function judgeTake(input: {
45
45
  readonly template: string;
46
46
  readonly shape?: string;
47
47
  readonly restsOn?: string;
48
+ /** An unchanged cone may receive its first missing judgment; vouching bytes is not judgment. */
49
+ readonly unpaid?: boolean;
48
50
  readonly witnessOf?: (coordinate: string) => string | undefined;
49
51
  }): Verdict & {
50
52
  readonly notOwned: readonly string[];
@@ -35,7 +35,7 @@ export function judgeTake(input) {
35
35
  const digest = fullDigest(storeOf(root), JSON.stringify({ ...envelope, effects: effects.map((e) => ({ kind: e.kind, status: e.status, at: e.at })) }));
36
36
  const refuse = (why) => ({ kind: 'refuse', why, envelope, digest, changed, notOwned });
37
37
  const met = (why) => ({ kind: 'fact', why, envelope, digest, changed, notOwned });
38
- if (!changed.length)
38
+ if (!changed.length && !input.unpaid)
39
39
  return refuse('nothing in the cone moved against what was vouched');
40
40
  const cone = locations.map((l) => region(l));
41
41
  const outside = changed.filter((coordinate) => !answers([point(coordinate)], cone));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lapxo/bound",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "Read the bounds you already wrote, fold them, and name the contradictions.",
6
6
  "main": "dist/cli/verb.js",