@lapxo/bound 0.1.3 → 0.1.5

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.
Files changed (70) hide show
  1. package/LICENSE +0 -1
  2. package/README.md +26 -5
  3. package/TARGET.bound +101 -22
  4. package/dist/cli/accept.js +21 -9
  5. package/dist/cli/owner.d.ts +2 -0
  6. package/dist/cli/owner.js +17 -2
  7. package/dist/cli/pass.js +15 -10
  8. package/dist/cli/place.js +8 -1
  9. package/dist/cli/verb.js +43 -3
  10. package/dist/fold/claims.js +5 -1
  11. package/dist/fold/closed.js +44 -13
  12. package/dist/fold/digests.js +5 -2
  13. package/dist/fold/observed.js +197 -174
  14. package/dist/fold/readers.d.ts +2 -0
  15. package/dist/fold/readers.js +3 -3
  16. package/dist/fold/resolved.js +6 -2
  17. package/dist/host/act-cost.d.ts +13 -0
  18. package/dist/host/act-cost.js +25 -0
  19. package/dist/host/adapters/modules/javascript.d.ts +1 -0
  20. package/dist/host/adapters/modules/javascript.js +48 -0
  21. package/dist/host/adapters/transport/http.d.ts +5 -0
  22. package/dist/host/adapters/transport/http.js +28 -0
  23. package/dist/host/capsule-process.d.ts +2 -1
  24. package/dist/host/capsule-process.js +24 -20
  25. package/dist/host/capsule.d.ts +1 -0
  26. package/dist/host/capsule.js +13 -16
  27. package/dist/host/cell-receipts.js +1 -1
  28. package/dist/host/content-store.d.ts +8 -0
  29. package/dist/host/content-store.js +31 -0
  30. package/dist/host/lifetime.d.ts +1 -0
  31. package/dist/host/lifetime.js +40 -0
  32. package/dist/host/objects.js +1 -1
  33. package/dist/host/ports/ingress.d.ts +24 -0
  34. package/dist/host/ports/ingress.js +81 -0
  35. package/dist/host/ports/transport.d.ts +1 -0
  36. package/dist/host/ports/transport.js +48 -0
  37. package/dist/host/process-lifetime.d.ts +11 -0
  38. package/dist/host/process-lifetime.js +12 -0
  39. package/dist/host/reading-closures.d.ts +28 -0
  40. package/dist/host/reading-closures.js +146 -0
  41. package/dist/host/release.js +24 -2
  42. package/dist/host/selected-capsules.js +38 -12
  43. package/dist/host/selected-topos.d.ts +4 -4
  44. package/dist/host/selected-topos.js +8 -30
  45. package/dist/host/source-content.d.ts +1 -1
  46. package/dist/host/source-content.js +15 -15
  47. package/dist/host/walk.d.ts +6 -0
  48. package/dist/host/walk.js +193 -0
  49. package/dist/observe/identity.d.ts +2 -0
  50. package/dist/observe/identity.js +3 -3
  51. package/dist/observe/regions.js +3 -5
  52. package/dist/observe/run.d.ts +2 -1
  53. package/dist/observe/run.js +5 -3
  54. package/dist/render/field.d.ts +1 -7
  55. package/dist/render/field.js +6 -12
  56. package/dist/render/names.d.ts +1 -1
  57. package/dist/render/names.js +1 -1
  58. package/dist/render/receipts.js +2 -1
  59. package/dist/render/view.js +16 -11
  60. package/docs/contracts/archive.md +11 -0
  61. package/docs/contracts/cli.md +11 -0
  62. package/docs/contracts/documents.md +35 -0
  63. package/docs/contracts/evidence-view.md +6 -0
  64. package/docs/contracts/publication.md +17 -0
  65. package/docs/contracts/typed-object.md +27 -0
  66. package/docs/contracts/view-walk.md +7 -0
  67. package/docs/contracts/views.md +29 -0
  68. package/docs/usage.md +6 -0
  69. package/package.json +6 -4
  70. package/receipts.bound +314 -94
@@ -19,7 +19,7 @@ export function resetsOnEqualEmits(lines) {
19
19
  }
20
20
  return [...named.values()].filter((ats) => ats.size > 1).length;
21
21
  }
22
- function emitted(store, root, module, kind, cases) {
22
+ function emitted(store, root, module, kind, cases, lifetime) {
23
23
  const laid = kind === 'process' ? mkdtempSync(join(tmpdir(), `${selfName()}-vectors-`)) : root;
24
24
  try {
25
25
  for (const one of kind === 'process' ? cases : []) {
@@ -28,7 +28,7 @@ function emitted(store, root, module, kind, cases) {
28
28
  writeFileSync(join(laid, one.place, name), text);
29
29
  }
30
30
  }
31
- const rows = runReader(resolve(root, module), laid, cases.map((one) => ({ place: one.place, ...(kind === 'js' ? { text: one.text ?? '' } : {}) })));
31
+ const rows = runReader(resolve(root, module), laid, cases.map((one) => ({ place: one.place, ...(kind === 'js' ? { text: one.text ?? '' } : {}) })), lifetime);
32
32
  if (cases.length && rows.every((mine) => !mine.length))
33
33
  return undefined;
34
34
  const said = rows.map((mine) => mine.filter((row) => !/^(cost|derived|vector-memo)\//.test(row.scope)).map((row) => JSON.stringify(row)).sort());
@@ -50,7 +50,7 @@ export function identityOf(input) {
50
50
  const known = mine.find((line) => fieldOf(line, 'measure') === 'extension' && fieldOf(line, 'at') === `place:${key}`);
51
51
  if (known !== undefined && fieldOf(known, 'value') === input.code)
52
52
  return { by: input.code, lines: [] };
53
- const emits = emitted(input.store, input.root, input.module, input.kind, JSON.parse(text).cases ?? []);
53
+ const emits = emitted(input.store, input.root, input.module, input.kind, JSON.parse(text).cases ?? [], input.lifetime);
54
54
  if (emits === undefined)
55
55
  return { by: input.code, lines: [] };
56
56
  const by = input.code;
@@ -5,13 +5,11 @@ import { createHash } from 'node:crypto';
5
5
  import { basename, dirname, join, relative } from 'node:path';
6
6
  import { CAPSULE, LOCK, canonical, matches, PROTOCOL } from '@lapxo/topos/wire';
7
7
  import { handed, readsOf } from '@lapxo/topos/capsule';
8
- import { STATES } from '@lapxo/obligations';
9
8
  import { foldCeilings } from "../fold/ceilings.js";
10
9
  import { fieldOf, wireLinesOf as linesOf } from "../fold/claims.js";
11
10
  import { isCeiling } from "../fold/configures.js";
12
11
  import { keyFor } from "../fold/keys.js";
13
12
  import { casesHeld, placedReadings } from "../fold/observed.js";
14
- import { verdictsFor } from "../fold/paid.js";
15
13
  import { capsuleAt as isWorld, placesIn, spoken } from "../fold/places.js";
16
14
  import { rolesOf } from "../fold/roles.js";
17
15
  import { ownLockOf } from "../fold/signed.js";
@@ -71,9 +69,8 @@ function askedOf(fold) {
71
69
  return fold.under ? [...new Set(capsuleOf(fold).filter((line) => fieldOf(line, 'scope').startsWith('region/') && fieldOf(line, 'role') === 'render').map((line) => fieldOf(line, 'scope').slice('region/'.length)))]
72
70
  .map((name) => ((n) => fact(`asked/${name}`, `${n}..${n}`, 'interval', 'count'))(pinnersOf(fold).map(at).filter((names) => names.has(name)).length)) : [];
73
71
  }
74
- /** The place's verdict line as counts: what the fold lands, forks and refuses, each of the object's four states, and the ceilings it meets. */
72
+ /** File-fold readings and their ceilings; this path computes no object encounters. */
75
73
  function verdictOf(fold) {
76
- const states = Object.values(verdictsFor(fold));
77
74
  const named = (line) => ((cut) => [line.slice(0, cut < 0 ? line.length : cut).trim(), line.slice(cut < 0 ? line.length : cut + 3).trim() || line])(line.indexOf(' · '));
78
75
  const here = (fold.under ?? '').replace(/\/$/, '');
79
76
  const others = new Set(here ? placesIn(fold.root).filter((place) => place !== here) : []);
@@ -86,7 +83,8 @@ function verdictOf(fold) {
86
83
  return !others.has(head);
87
84
  };
88
85
  return [['claims', fold.claims], ['forks', fold.forks.length + (fold.second.verdict === 'forks' ? 1 : 0)], ['refused', fold.refused.length], ['vacuous', fold.vacuous], ['history', fold.history.length],
89
- ['met', fold.ceilings.read], ['short', fold.ceilings.short.length], ['over', fold.ceilings.over.length], ...STATES.map((one) => [one, states.filter((state) => state === one).length])].map(([name, n]) => fact(`verdict/${name}`, `${n}..${n}`, 'interval', 'count'))
86
+ ['met', fold.ceilings.read], ['short', fold.ceilings.short.length], ['over', fold.ceilings.over.length]].map(([name, n]) => fact(`verdict/${name}`, `${n}..${n}`, 'interval', 'count'))
87
+ .concat([fact('verdict/computation', 'readings'), fact('verdict/encounters', 'uncomputed')])
90
88
  .concat(fold.ceilings.short.filter((one) => mine(named(one)[0])).map((one) => (([scope, reading]) => fact(`unpaid/${scope}`, reading))(named(one))))
91
89
  .concat(fold.ceilings.over.filter((one) => mine(named(one)[0])).map((one) => (([scope, reading]) => fact(`outside/${scope}`, reading))(named(one))))
92
90
  .concat(fold.ceilings.unread.filter(mine).map((scope) => fact(`unpaid/${scope}`, 'unread')))
@@ -1,3 +1,4 @@
1
+ import type { ReaderLifetime } from '@lapxo/topos/wire';
1
2
  export type Kind = 'js' | 'process';
2
3
  /** The kinds this host starts. A reader of any other kind is signed and stays potential: nothing here runs it. */
3
4
  export declare const runs: (kind: string) => kind is Kind;
@@ -26,5 +27,5 @@ export declare const hostOf: () => string;
26
27
  * the file it is handed or alone when it reads the place by running it, as the region it was matched for when its
27
28
  * capsule reads with several, and answers one list of claims per place.
28
29
  */
29
- export declare function runReader(module: string, root: string, inputs: readonly Input[]): readonly (readonly Row[])[];
30
+ export declare function runReader(module: string, root: string, inputs: readonly Input[], limits?: ReaderLifetime): readonly (readonly Row[])[];
30
31
  export {};
@@ -1,3 +1,4 @@
1
+ import { boundedProcess } from "../host/process-lifetime.js";
1
2
  import { spawnSync } from 'node:child_process';
2
3
  import { existsSync } from 'node:fs';
3
4
  import { PROTOCOL } from '@lapxo/topos/wire';
@@ -13,7 +14,7 @@ export const hostOf = () => processOf('host');
13
14
  * the file it is handed or alone when it reads the place by running it, as the region it was matched for when its
14
15
  * capsule reads with several, and answers one list of claims per place.
15
16
  */
16
- export function runReader(module, root, inputs) {
17
+ export function runReader(module, root, inputs, limits) {
17
18
  if (!inputs.length)
18
19
  return [];
19
20
  const requests = inputs.map((input) => ({
@@ -23,8 +24,9 @@ export function runReader(module, root, inputs) {
23
24
  const reader = readerOf(module);
24
25
  if (!existsSync(reader.path))
25
26
  throw new Error(`REFUSE·reader ${module} unavailable; its declared capability needs an admitted provider`);
26
- const ran = spawnSync(process.execPath, [...reader.flags, hostOf(), reader.path, module], { cwd: root, input: JSON.stringify(requests), encoding: 'utf8', maxBuffer: 1 << 28 });
27
- if (ran.error)
27
+ const args = [...reader.flags, hostOf(), reader.path, module];
28
+ const ran = limits === undefined ? spawnSync(process.execPath, args, { cwd: root, input: JSON.stringify(requests), encoding: 'utf8', maxBuffer: 1 << 28 }) : boundedProcess(process.execPath, args, JSON.stringify(requests), limits, root);
29
+ if ('error' in ran && ran.error)
28
30
  throw Object.assign(new Error(`${module}: reader process failed: ${ran.error.message}`), { cause: ran.error });
29
31
  if (ran.status !== 0)
30
32
  throw new Error(`${module}: reader exited ${ran.status ?? `with signal ${ran.signal}`}\n${ran.stderr ?? ''}${ran.stdout ?? ''}`);
@@ -1,9 +1,3 @@
1
1
  import type { PlaceFold } from '../cli/place.ts';
2
- /**
3
- * The field of a place at resolution N: every bound placed at the place or at none, in the state its poles give, and
4
- * every coordinate cut to its first N steps in the worst state it holds. Interval poles with no value in common
5
- * conflict, as two signers on one key do; an alphabet that permits none is a ceiling like any other. A value read
6
- * outside the poles is forbidden; a bound nothing read, a reader that refused and a demand unpaid are required; the
7
- * rest is free. It is read off the region summaries and the landed readings, and no reader runs.
8
- */
2
+ /** Host file-region readings, grouped by coordinate prefix. These statuses do not compute object encounters. */
9
3
  export declare function field(fold: PlaceFold, at: number): readonly string[];
@@ -3,15 +3,9 @@ import { placesIn } from "../fold/places.js";
3
3
  import { placedAt } from "../fold/reach.js";
4
4
  import { polesOf, rankOf, unpackRegions } from "../fold/region.js";
5
5
  import { INTERVALS } from '@lapxo/topos/forms';
6
- const WORST = ['CONFLICT', 'FORBIDDEN', 'REQUIRED', 'FREE'];
6
+ const WORST = ['disagreement', 'outside', 'unanswered', 'met'];
7
7
  const empty = (ceiling) => ceiling !== undefined && 'lo' in ceiling && !INTERVALS.inhabited(ceiling);
8
- /**
9
- * The field of a place at resolution N: every bound placed at the place or at none, in the state its poles give, and
10
- * every coordinate cut to its first N steps in the worst state it holds. Interval poles with no value in common
11
- * conflict, as two signers on one key do; an alphabet that permits none is a ceiling like any other. A value read
12
- * outside the poles is forbidden; a bound nothing read, a reader that refused and a demand unpaid are required; the
13
- * rest is free. It is read off the region summaries and the landed readings, and no reader runs.
14
- */
8
+ /** Host file-region readings, grouped by coordinate prefix. These statuses do not compute object encounters. */
15
9
  export function field(fold, at) {
16
10
  if (fold.regions === undefined)
17
11
  return ['GREY field · this fold carries no region summaries; it is read again at the next fold'];
@@ -25,10 +19,10 @@ export function field(fold, at) {
25
19
  ...regions.bounds.filter((bound) => here(bound.line)).map((bound) => {
26
20
  const ceiling = (poles.get(bound.region) ?? poles.set(bound.region, polesOf(regions, bound.region)).get(bound.region)).get(`${bound.question} ${bound.measure}`)?.ceiling;
27
21
  const got = rankOf(regions, bound, own);
28
- return [fieldOf(bound.line, 'scope'), empty(ceiling) ? 'CONFLICT' : got.bars || got.sums ? 'FORBIDDEN' : got.met ? 'FREE' : 'REQUIRED'];
22
+ return [fieldOf(bound.line, 'scope'), empty(ceiling) ? 'disagreement' : got.bars || got.sums ? 'outside' : got.met ? 'met' : 'unanswered'];
29
23
  }),
30
- ...fold.missing.filter(here).map((line) => [fieldOf(line, 'scope'), 'REQUIRED']),
31
- ...fold.forks.flatMap((fork) => fork.lines.slice(0, 1)).filter(here).map((line) => [fieldOf(line, 'scope'), 'CONFLICT']),
24
+ ...fold.missing.filter(here).map((line) => [fieldOf(line, 'scope'), 'unanswered']),
25
+ ...fold.forks.flatMap((fork) => fork.lines.slice(0, 1)).filter(here).map((line) => [fieldOf(line, 'scope'), 'disagreement']),
32
26
  ];
33
27
  const cells = new Map();
34
28
  for (const [scope, state] of states) {
@@ -39,7 +33,7 @@ export function field(fold, at) {
39
33
  const ordered = [...cells].sort((a, b) => WORST.indexOf(a[1].state) - WORST.indexOf(b[1].state) || a[0].localeCompare(b[0]));
40
34
  return [
41
35
  '## field', '', '```',
42
- `FIELD @${at} · ${cells.size} cells · ${states.length} bounds · ${WORST.map((state) => `${state} ${ordered.filter(([, one]) => one.state === state).length}`).join(' · ')}`,
36
+ `FIELD @${at} · ${cells.size} groups · ${states.length} bounds · readings · no encounters computed · ${WORST.map((state) => `${state} ${ordered.filter(([, one]) => one.state === state).length}`).join(' · ')}`,
43
37
  ...ordered.map(([cell, one]) => `FIELD ${cell} · ${one.state} · ${one.bounds} bounds`),
44
38
  '```',
45
39
  ];
@@ -1,3 +1,3 @@
1
1
  /** The regions bound renders itself, by name: a view that asks any other is answered by a capsule that declares it, or refused whole. */
2
- export declare const REGION_NAMES: readonly ["receipts", "help", "lines", "red", "forks", "programs", "why", "sign", "take", "history", "field"];
2
+ export declare const REGION_NAMES: readonly ["receipts", "help", "lines", "red", "forks", "programs", "why", "sign", "take", "history", "field", "evidence"];
3
3
  export type RegionName = (typeof REGION_NAMES)[number];
@@ -1,4 +1,4 @@
1
1
  /** The regions bound renders itself, by name: a view that asks any other is answered by a capsule that declares it, or refused whole. */
2
2
  export const REGION_NAMES = [
3
- 'receipts', 'help', 'lines', 'red', 'forks', 'programs', 'why', 'sign', 'take', 'history', 'field',
3
+ 'receipts', 'help', 'lines', 'red', 'forks', 'programs', 'why', 'sign', 'take', 'history', 'field', 'evidence',
4
4
  ];
@@ -23,7 +23,8 @@ export function receiptRegion(fold, at) {
23
23
  const contract = wireLine(ownLock(), 'receipt-instrument');
24
24
  const coordinate = contract === undefined ? undefined : fieldOf(contract, 'value');
25
25
  const implementation = coordinate === undefined ? undefined : instrumentDigest(fold.store, sourceOf(), [], ownRoot(), ownLock());
26
- const observed = [...receiptsOf(fold), ...(coordinate && implementation ? [canonical({ scope: coordinate, role: 'writes', form: 'alphabet', measure: 'digest', value: implementation, at: `place:${implementation}`, by: 'bound' })] : [])];
26
+ // The current implementation seal is metadata, not an observation carried from a previous fold.
27
+ const observed = [...receiptsOf(fold).filter(line => !coordinate || fieldOf(line, 'scope') !== coordinate), ...(coordinate && implementation ? [canonical({ scope: coordinate, role: 'writes', form: 'alphabet', measure: 'digest', value: implementation, at: `place:${implementation}`, by: 'bound' })] : [])];
27
28
  const hash = (bytes) => bytesDigest(fold.store, new TextEncoder().encode(bytes));
28
29
  const head = keyOf(fold.store, 'attest');
29
30
  const projection = receiptProjection(observed, fields, hash, head ? [head] : []);
@@ -7,26 +7,29 @@ import { capsuleAnswers, capsuleRegions, capsuleViews } from "./capsule.js";
7
7
  import { declaredBy } from "../observe/regions.js";
8
8
  import { readersBehind } from "../fold/observed.js";
9
9
  import { LOCK, canonical, matches } from '@lapxo/topos/wire';
10
- import { STATES } from '@lapxo/obligations';
11
10
  import { fieldOf, foldClaims, selfName } from "../fold/claims.js";
12
11
  import { keepRender, keptRender } from "../fold/kept.js";
13
- import { bytesDigest } from "../fold/digests.js";
14
- import { writerFor } from "../fold/signers.js";
12
+ import { bytesDigest, signaturesOf } from "../fold/digests.js";
13
+ import { authorityFor, rootSigner, writerFor } from "../fold/signers.js";
15
14
  import { lockLines } from "../fold/keys.js";
15
+ import { appliedIn } from "../fold/signed.js";
16
+ import { ledgerLines } from "../land/ledger.js";
16
17
  import { horizonOf, moved, shapeLines } from "./shape.js";
17
18
  import { rankLines } from "../fold/rank.js";
18
19
  import { differing, regionsOf } from "../fold/region.js";
19
- import { verdictsFor } from "../fold/paid.js";
20
20
  import { field } from "./field.js";
21
21
  import { helpLines } from "../cli/names.js";
22
+ /** Authenticated delivery history is evidence, not the place's normative standing. */
23
+ const evidence = (fold) => {
24
+ const authority = authorityFor(lockLines(fold.store), rootSigner(fold.root), signaturesOf(fold.store).admitted);
25
+ const place = (fold.under ?? '').replace(/\/$/, '');
26
+ const deliveries = place ? appliedIn(fold.root, place)
27
+ : [...new Set(authority.admitted.flatMap(key => ledgerLines(fold.store, key.id)))];
28
+ return deliveries
29
+ .filter(line => authority.of(line).kind === 'admitted');
30
+ };
22
31
  const block = (name, lines) => (lines.length ? [`## ${name}`, '', '```', ...lines, '```'] : []);
23
32
  const seconds = (ms) => `${(ms / 1000).toFixed(1)} s`;
24
- const statesOf = (fold) => {
25
- const held = new Map();
26
- for (const one of Object.values(verdictsFor(fold)))
27
- held.set(one, (held.get(one) ?? 0) + 1);
28
- return STATES.flatMap((one) => (held.get(one) ? [`${one} ${held.get(one)}`] : []));
29
- };
30
33
  const programs = (fold) => {
31
34
  const median = fold.costs.length ? [...fold.costs].sort((a, b) => a - b)[Math.floor(fold.costs.length / 2)] ?? 0 : 0;
32
35
  const turned = moved(fold);
@@ -34,12 +37,13 @@ const programs = (fold) => {
34
37
  const refusedByReader = fold.observed.filter((line) => fieldOf(line, 'scope') === 'refuse/reader').length;
35
38
  const c = fold.ceilings;
36
39
  return block('programs', [
37
- `PROGRAMS${fold.under ? ` ${fold.under}` : ''} ${[`${fold.claims} claims`, ...statesOf(fold), `${fold.history.length} history`].join(' · ')}`
40
+ `PROGRAMS${fold.under ? ` ${fold.under}` : ''} ${[`${fold.claims} claims`, `${fold.history.length} history`].join(' · ')}`
38
41
  + ` · ${fold.forks.length + (fold.second.verdict === 'forks' ? 1 : 0)} forks · ${fold.grey.length} grey · ${fold.refused.length} refused · ${fold.vacuous} vacuous`
39
42
  + ` · ${secondName()} ${fold.second.verdict}${fold.second.verdict === 'agrees' && !fold.second.external ? ', never disagreed' : ''}`
40
43
  + ` · store ${fold.observed.length} observed${refusedByReader ? ` · ${refusedByReader} refuse·reader` : ''}`
41
44
  + (fold.under ? ` · ceilings ${c.read} met here · ${c.short.length} short · ${c.over.length} over`
42
45
  : ` · ceilings ${c.read}/${c.total} read · ${c.short.length} short · ${c.over.length} over · ${c.unread.length} unread${c.vacuous.length ? ` · ${c.vacuous.length} vacuous unread` : ''}`)
46
+ + ' · readings · no encounters computed'
43
47
  + ` · ${fold.effects} · take ${fold.costs.length ? seconds(fold.costs[fold.costs.length - 1] ?? 0) : 'none'} last`
44
48
  + (fold.costs.length > 1 ? ` · ${seconds(median)} median of ${fold.costs.length}` : ''),
45
49
  ...shapeLines(fold),
@@ -134,6 +138,7 @@ const REGIONS = {
134
138
  receipts: (fold) => receiptRegion(fold, 1),
135
139
  help: () => helpLines(),
136
140
  lines: (fold) => fold.standing,
141
+ evidence,
137
142
  red, forks, programs, why, sign, take, history,
138
143
  field: (fold) => field(fold, 3),
139
144
  };
@@ -0,0 +1,11 @@
1
+ # Exact release artifact
2
+
3
+ Packing 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.
4
+
5
+ The 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.
6
+
7
+ The 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.
8
+
9
+ This 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.
10
+
11
+ Rendering 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.
@@ -0,0 +1,11 @@
1
+ # fold
2
+
3
+ `bound fold` reads the admitted place. Configuration output names readings and says no encounters computed; its counts are not independent-origin states. A declared cells view projects admitted typed history into Obligations. A selected world defines other views; its contract decides when empty output is valid. A refusal or nonzero status wins over any parseable diagnostic stdout. `--check` verifies receipts without inventing a missing reading. The published evidence vector folds fresh places, preserves admitted key attribution, reads a native receipt and checks exact withdrawals. The typed-object quartet covers object states separately.
4
+
5
+ # land
6
+
7
+ `bound land <lot>` admits authenticated lines through the same boundary used by signing and previews. Authority, coverage, historical wire and typed context remain distinct checks. Unknown wire and tampered signatures refuse. Exact redelivery returns ONCE; it does not append another origin or grant new authority. Withdrawals remain exact under their declared contract. A refusal does not append a partial act. The published evidence vector lands fresh places, refuses unauthorized writes and tampering, redelivers signed bytes and exercises exact withdrawals. The signing-port vector additionally checks interrupted or invalid command responses do not land a partial lot.
8
+
9
+ # sign
10
+
11
+ `bound sign <lot>` returns canonical signed lines after validating the whole lot. The admitted key selects a declared signer; `--signer` selects the same port explicitly. File and command mechanisms use one port. Topos signing-lot/1 frames canonical bytes in lot order, one invocation per lot, and returns signatures and public-key IDs. Verification checks the admitted public key, independently of the mechanism. A command is invoked without a shell and under declared bounds. No secret output is disclosed in refusals. Missing, invalid, partial, timed-out or failed responses refuse; `land` cannot commit their partial output. The sample compares file and command signatures and landed lines, checks invocation count and ledger hashes, and refuses an unknown wire version. The sample uses ephemeral keys outside the place; no owner key is included.
@@ -0,0 +1,35 @@
1
+ # Explanation — historical profile
2
+
3
+ The declared view selects idea, what-holds and refuses from the byte-pinned historical document provider. The place owns its language and prose. Idea renders its own heading and body. The other two regions require their declared law readings or captured refusals; absent evidence supplies no invented result. The executable sample uses two unrelated places, checks the complete explanation file, repeats the product fold without a file difference and asks the named view directly. It also refuses a well-formed view asking an unoffered region. This quartet proves own-prose projection and absence under this profile; it does not certify law readings, a rejection corpus, typed-object states or the pending general document contract. Bound does not parse this prose.
4
+
5
+ # README — historical profile
6
+
7
+ The declared view selects hero@3, commands@3 and idea@3 from the byte-pinned historical document provider. The place supplies its name, tagline, language, sentence rule and idea. Commands and measured badges are absent in the sample: no command, number or success is invented to fill them. Two unrelated places check the generated README, a second unchanged product fold and the named view; a declared unoffered region refuses by name. The implementation member is verified against the admitted historical artifact. This quartet proves the selected prose profile, not command execution, badges with measured values or a general document grammar. The eight text@3 demands remain unpaid.
8
+
9
+ # Citation file — historical profile
10
+
11
+ The declared view asks the pinned document provider for cff at resolution 3. It projects the place name, version and optional citation metadata into CFF text. The sample uses the exact implementation member from the admitted historical artifact, names its hash and license, and exercises two unrelated places through the compiled CLI. It checks complete citation bytes and two equal readings; title and version follow each place. An unoffered region refuses by view name. Missing optional metadata is omitted; missing name can produce an empty answer under this historical profile. Rendering is not verification of a scientific claim or an external DOI. This pinned profile does not implement the pending general document contract.
12
+
13
+ # Guide — historical profile
14
+
15
+ The declared view asks seq from the pinned historical document provider. The place owns page/seq lines and their heading. Canonical input order supplies the steps; the provider numbers that order and writes the requested shape. The executable sample uses two unrelated procedures, checks their complete Markdown and reads each view twice without differences. A declared view with an unoffered region refuses by name. An empty step set may have an empty answer; it is not invented evidence. A rendered instruction does not prove that instruction was executed. The implementation bytes remain the existing pinned profile, not a document grammar inside Bound.
16
+
17
+ # Reference — historical profile
18
+
19
+ The declared view combines term, set and ref from the pinned historical document provider. The profile projects the place term and meaning, its selected world names and links to its declared Markdown shapes. The executable sample runs two unrelated places, checks their own term and meaning, the actual selected world and relative guide link, and captures two identical CLI readings. A view asking an unoffered region refuses by name. Missing terms or links can yield empty component answers; these are not measurements or a claim that obligations were paid. These historical regions and selectors belong to the selected Topos; Bound supplies verified inputs and dispatch only. The general document contract remains unpaid.
20
+
21
+ # Manifest render profile
22
+
23
+ This declared view uses the selected verbatim-prose provider at text@3. The place assigns its complete manifest text to its output shape; Bound verifies and dispatches the selected offer and writes that shape. The provider does not infer a package schema, dependency graph or fields from the filename. The sample renders two places with distinct JSON bodies twice and checks exact file bytes. Two distinct prose bodies assigned to the same shape refuse; earlier outputs remain unchanged. This proves rendering, not that arbitrary JSON is an installable package.
24
+
25
+ # Workflow render profile
26
+
27
+ This declared view uses the selected verbatim-prose provider at text@3. The place owns the workflow text and its shape; Bound does not infer a forge or manufacture pipeline steps. The sample writes distinct YAML bodies in two places, reads the rendered files twice and compares exact bytes. Conflicting bodies for one shape refuse without replacing prior outputs. This is a render contract, not evidence that a forge executed, staged or published a release. The release pipeline has its separate artifact gate.
28
+
29
+ # Usage render profile
30
+
31
+ This declared view uses the selected verbatim-prose provider at text@3. A prose line with measure=text and the requested shape supplies its own body. The sample renders distinct Markdown bodies in two places twice and compares exact bytes. Multiple identical bodies are one text; differing bodies for one shape refuse. It invents no sections or documentation schema. This existing profile does not pay the eight general-document demands or validate commands that prose happens to mention; executable commands require their own captured vectors.
32
+
33
+ # Build configuration — historical profile
34
+
35
+ The declared tsconfig view asks the admitted package provider for its build region. It projects the place's build/* lines whose shape matches the requested file: true and false become JSON booleans, other option values remain strings, and include separates its declared alternatives. The byte-fixed fixture names the implementation member and its artifact independently; Bound does not interpret compiler options. Two unrelated places exercise the compiled CLI, check the complete generated configuration and two byte-identical readings. A declared view asking an unoffered region refuses by name. This profile renders configuration; it does not validate compiler options or claim a successful build. An empty option set renders an empty compilerOptions object. It is a pinned historical profile, not the pending general document contract.
@@ -0,0 +1,6 @@
1
+ # Authenticated evidence view
2
+
3
+ The 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.
4
+
5
+
6
+ The 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.
@@ -0,0 +1,17 @@
1
+ # Published contracts
2
+
3
+ Every public surface names its contract, accepted sample, captured executable vector and rejected sample. Missing members, differing artifact digests and failed vectors remain unpaid. Publication conformance is distinct from installed-artifact acceptance.
4
+
5
+ The selected Topos projects each quartet as a reading through the existing wire. Execution proofs are dependency readings; identical vector bytes share one proof. Each reading names its exact handed inputs and dependent receipt digests. Bound verifies those closures and keeps native count/bytes receipts by digest. A closed reading costs no new execution. The publication aggregate reads the quartet receipts; it never starts an inventory batch.
6
+
7
+ Execution slots, per-execution timeout and response bytes are declared resource lines in the selected Topos. Bounds remain unchanged. A failed reading is not cached as a successful proof. Earlier completed readings stay verified, so a later refusal does not force them to execute again. Changed, missing or corrupt bytes cannot reuse their receipts. Output and execution history retain their exact coordinates.
8
+
9
+ ## Act cost
10
+
11
+ Each declared reading and each host invocation is measured separately. The total duration of a pass is a diagnostic; it is not the cost of one indivisible act. The cost/act ceiling reads the largest measured act or the remaining unpartitioned host work. Nested invocations are not charged twice. A slow or refused act retains its cost. Native reading receipts retain measured seconds separately from semantic identity; reusing a receipt performs no new reader execution. Missing historical durations are not invented as zero.
12
+
13
+ ## Public verification
14
+
15
+ Full-resolution native reading receipts carry the verified canonical UTF-8 input closure in the bytes row and the verified output in the count row, through the wire’s existing about field. Count, digest and measured duration keep their existing meanings. The host verifies the supplied bytes against those digests before reuse; an altered supplied carrier is not replaced by a cached copy. Historical local-only receipts still require their authentic CAS bytes. No private ledger or store is needed to verify a complete public receipt.
16
+
17
+ File-region seals hash configuration through Topos’s existing publication projection. Admission envelopes and retired history stay in the authority ledger; live declarations and ordinary file bytes remain inputs. Object history uses its own contract. A public checkout must carry receipts made for its actual files and compiled reader, not seals copied from a different tree. Verification does not run readers, fetch dependencies, refresh receipts or grant authority.
@@ -0,0 +1,27 @@
1
+ ## Typed cell, claim and mark records
2
+
3
+ The object profile is selected by admitted `wire/object/*` claims in a historical wire snapshot. The epoch of `wire/object/types` is its activation E; a typed record must have epoch >= E. An older record keeps the older grammar. Merely adding object words to `wire/fields` does not admit a typed profile.
4
+
5
+ `fromLine` selects grammar before validating required fields: a record without `type` remains configuration, retaining its required `at`, `role`, `form`, `measure` and `value`; a typed record selects its exact required/allowed row. Configuration cannot carry object-only fields. An incomplete typed record receives no configuration defaults. The parse result distinguishes configuration from cell/claim/mark. `sign=+1|-1` is an object act, `sig` its signature envelope, and a host sign operation produces that envelope.
6
+
7
+ The common object envelope is `type`, `scope`, `id`, `epoch`, `by`, `sig`. Object records reject `at`: epoch orders acts, and `widens` names a local join witness. The following is the declared reference profile. The admitted row alphabets, not this table or a host decoder, are the source of required/allowed field permission.
8
+
9
+ | Row | Fields in addition to the common envelope | Meaning |
10
+ | --- | --- | --- |
11
+ | cell | form, measure, params, restsOn, topos | Define a cell and its selected form/context. |
12
+ | claim/positive | sign, origin, value | Observe an encoded span, sign=+1. |
13
+ | claim/negative | sign, takes | Withdraw an exact claim ID, sign=-1. |
14
+ | mark/travelling | sign, pole, reach, value | Ceiling sign: sign=+1, pole=ceiling, reach=travels. |
15
+ | mark/local | sign, pole, reach, value, widens | Local join: sign=+1, pole=ceiling, reach=local; another mark, retaining the travelling sign. |
16
+ | mark/floor-travelling | sign, pole, reach, value | Travelling require: sign=+1, pole=floor, reach=travels; no widens. |
17
+ | mark/negative | sign, takes | Withdraw an exact mark ID, sign=-1; no pole/reach/widens. |
18
+
19
+ Each row has both `wire/object/required/<row>` and `wire/object/allowed/<row>`. Unknown keys, missing required keys, floor/local, floor+widens, and travelling widening refuse without coercion. A configuration demand is unrelated to a floor mark. `by` authenticates a signing key; it is not an independent observation origin.
20
+
21
+ For a cell, `restsOn=none` represents no parents; otherwise it is a canonical byte-ordered alphabet of coordinates. Several parents are permitted. Only declared cell-coordinate edges form object rest; a directory prefix, a configuration artifact digest, and a host source location do not. Context validation rejects reachable cycles before algebraic parts are requested.
22
+
23
+ The cell's `topos` names folded standing, and its `params` identifies declared parameter bytes. A selected provider decodes values and supplies origin/witness authorization from admitted evidence. A host does not infer interval endpoints, map a key to an origin, or accept widens as its own witness. Missing pin, artifact, decoder, origin or witness refuses by cause. Cell definitions and pins are immutable in this profile; migration is not inferred.
24
+
25
+ `objectHistory` preserves typed history separately from configuration; `validateObjectContext` checks IDs, cell ownership, exact takes, witness order and declared rest under the selected context. Exact redelivery is idempotent; one ID with different canonical content refuses. Signature-envelope differences never bypass verification.
26
+
27
+ After admission, the instrument projects the acts into Obligations. Sign and require travel along declared rest; a witnessed join is local. Descendants inherit travelling marks without local widening. Live exact-ID withdrawals remain confined to their authenticated history. Keys, snapshots, signing devices and repeated receipts do not create independent origins. Compatible meets are not forks. Object states and their precedence come from Obligations; configuration folds do not compute object encounters.
@@ -0,0 +1,7 @@
1
+ # Walk
2
+
3
+ `bound fold --as walk@<resolution>` compares the admitted place with an authenticated peer inventory. Resolution is interpreted by the declared Topos selection and projection contract; it is not restricted to three fixed numbers. The wire declares region membership, context, origin and cuts. The output names touched regions, open regions and payload bytes; protocol and imported bytes carry their own units.
4
+
5
+ Foreign history retains its signed origin epoch. Sender keys authenticate that history and never grant coverage or independent origins in the receiver. Whole-region prefixes are verified before ingress. Import and the receiver-signed local receipt commit atomically; only that receipt advances the receiver's local epoch. Foreign withdrawals are confined to the same authenticated origin and exact identifier. A repeated valid delivery adds no lines and retains its existing import receipt. A rejected or interrupted ingress adds neither evidence nor a receipt.
6
+
7
+ The published sample uses the same compiled public reader on measurement and artifact places. It compares equal summaries, opens a differing region, exchanges at intermediate declared resolutions, converges by union, retains disagreement and verifies replay after a later local act. It rejects tampered payloads, missing records, unauthorized signatures, non-prefix epochs and undeclared context changes. It interrupts a real receiver signer and verifies unchanged ingress and local history. Dead-owner recovery is a separate host action; this view does not silently recover it. The typed object's origin-local claims and withdrawals are a separate conformance vector, not inferred from configuration counts.
@@ -0,0 +1,29 @@
1
+ # Help view
2
+
3
+ A declared help view projects the instrument verb and flag table. It is generated from that table, not copied prose or a claim that another world is supported. Asking it does not authorize a line or call a selected external reader. The sample declares view/help value=help, checks the printed three verbs and refuses a declared view whose region has no provider.
4
+
5
+ # Lines view
6
+
7
+ A declared lines view projects canonical normative standing as wire lines. It is a configuration reading; it does not compute encounters or turn evidence into authority. Live exact withdrawals disappear from normative standing while authenticated evidence remains inspectable through its own view. The sample verifies signatures and attribution, redelivery ONCE, exact withdrawals, tampering and uncovered writes. A declared missing provider refuses rather than returning an invented reading.
8
+
9
+ # Receipts view
10
+
11
+ The native receipt view projects the fold through the admitted Topos receipt contract. The sample uses the published place profile receipts@8|receipts@0|receipts@1: observations, summary and current region bytes. These are that profile’s declared projections, not a universal enumeration of resolutions. A receipt identifies the actual observed set; it is not an origin or a valuation. The sample obtains a native receipt, verifies its signed delivery from an attest-class key through evidence, and checks idempotent delivery. The refused sample names an uncovered write, tampered signature and declared view without a provider. No harness-written JSON is used as a receipt.
12
+
13
+ ## Public verification
14
+
15
+ Full-resolution native reading receipts carry the verified canonical UTF-8 input closure in the bytes row and the verified output in the count row, through the wire’s existing about field. Count, digest and measured duration keep their existing meanings. The host verifies the supplied bytes against those digests before reuse; an altered supplied carrier is not replaced by a cached copy. Historical local-only receipts still require their authentic CAS bytes. No private ledger or store is needed to verify a complete public receipt.
16
+
17
+ File-region seals hash configuration through Topos’s existing publication projection. Admission envelopes and retired history stay in the authority ledger; live declarations and ordinary file bytes remain inputs. Object history uses its own contract. A public checkout must carry receipts made for its actual files and compiled reader, not seals copied from a different tree. Verification does not run readers, fetch dependencies, refresh receipts or grant authority.
18
+
19
+ # Why a coordinate
20
+
21
+ `bound fold <coordinate> --as why` explains the live declarations whose exact `needs` member or `shape` names that coordinate. It prints the selector, witness and value. It does not compute an object encounter or infer authority from a path. The published sample bootstraps two independent places, explains each declared source coordinate and prints `OPEN` for a coordinate no declaration names. That absence is not zero, green or a state. A declared view with no provider refuses by name with a nonzero status. Calling why without a coordinate is not this sample’s acceptance vector; its empty historical capture pays nothing.
22
+
23
+ # Declared programs
24
+
25
+ The programs view asks the selected Topos demand-status projection at resolution 8. Selection, minimum, evidence, elapsed reading and time ceiling coordinates belong to that Topos contract; Bound only hands admitted declarations and region receipts. Program status is derived from that evidence and the declared dependency graph. A demand with no evidence remains unread, its dependant remains blocked, and a missing elapsed reading keeps deadline unread. No cell encounter, origin count or information quantity is computed by this view. The sample uses the published SDK implementation on two unrelated demand chains, captures equal readings twice, names the next unblocked coordinate, and refuses dependency cycles. It does not provide stage conformance evidence or claim either program closed.
26
+
27
+ # Demand card
28
+
29
+ The declared card view asks the selected Topos demand-card projection at resolution 8. It reads the selected demand coordinates, their explicit dependencies and the handed evidence region under selectors declared by that Topos. It does not infer progress from files or convert a declaration into proof. A requirement without evidence is unread; an unpaid predecessor blocks its dependant. The next coordinate is an unblocked unpaid demand. Deadline is unread when no elapsed receipt is handed; absence is not zero. These labels describe program evidence, not Obligations cell states. The sample pins the implementation member from the published Topos SDK, folds two unrelated places twice with equal stdout and refuses a declared dependency cycle. This sample intentionally has no evidence to close either program; it certifies the projection of absence and order, not stage acceptance.
package/docs/usage.md CHANGED
@@ -51,3 +51,9 @@ The accepted TARGET is independent of a contributor's scan. Commit native receip
51
51
  A contribution is a proposed lot with the leaf changes rendered from it. Send that lot for admission by the team's coverage. Do not submit hand-edited lock output as already accepted. Check secrets, extra bound files, foreign vendoring and uncaptured page claims before review.
52
52
 
53
53
  A review includes the product fold, meaningful suites and verification of the rendered bytes. Preserve their actual output and exit status.
54
+
55
+ ## Declaring a demand
56
+
57
+ A new demand records what remains to be proved. Admission does not create conformance evidence or pay it. An OWED line after land says the declaration was admitted and remains unpaid. Signing authority and conformance evidence are separate inputs.
58
+
59
+ The selected program projection reads declared requirements and handed evidence. Missing evidence stays unread; a missing elapsed-time reading is not zero. A dependency cannot close before its requirements and predecessors. Declaring a plan never certifies a release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lapxo/bound",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
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",
@@ -13,7 +13,7 @@
13
13
  "./package.json": "./package.json"
14
14
  },
15
15
  "scripts": {
16
- "test": "node --import ./test/setup.ts --test test/*.test.ts",
16
+ "test": "node --import ./test/setup.ts --test --test-concurrency=2 test/*.test.ts",
17
17
  "clean": "rm -rf dist .tsbuildinfo* tsconfig.tsbuildinfo",
18
18
  "build": "node tools/build.mjs",
19
19
  "prepack": "npm run build"
@@ -26,13 +26,15 @@
26
26
  "TARGET.bound",
27
27
  "receipts.bound",
28
28
  "docs/usage.md",
29
- "docs/readme-assets/atlas.svg"
29
+ "docs/readme-assets/atlas.svg",
30
+ "docs/contracts/*.md"
30
31
  ],
31
32
  "author": "Lapxo",
32
33
  "license": "MIT",
33
34
  "dependencies": {
34
35
  "@lapxo/obligations": "0.3.5",
35
- "@lapxo/topos": "0.1.8"
36
+ "@lapxo/topos": "^0.1.11",
37
+ "acorn": "8.19.0"
36
38
  },
37
39
  "devDependencies": {
38
40
  "@types/node": "^20.0.0",