@intentius/chant 0.90.0 → 0.91.0

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 (164) hide show
  1. package/dist/cli/handlers/components.d.ts +8 -0
  2. package/dist/cli/handlers/components.d.ts.map +1 -1
  3. package/dist/cli/handlers/operator.d.ts +14 -0
  4. package/dist/cli/handlers/operator.d.ts.map +1 -1
  5. package/dist/cli/handlers/run.d.ts.map +1 -1
  6. package/dist/cli/main.d.ts.map +1 -1
  7. package/dist/cli/mcp/workspace-tools.d.ts +6 -4
  8. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  9. package/dist/cli/registry.d.ts +31 -0
  10. package/dist/cli/registry.d.ts.map +1 -1
  11. package/dist/components/verbs/vuln-scan.d.ts +72 -0
  12. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  13. package/dist/lifecycle/git.d.ts +40 -5
  14. package/dist/lifecycle/git.d.ts.map +1 -1
  15. package/dist/lifecycle/lease.d.ts +72 -16
  16. package/dist/lifecycle/lease.d.ts.map +1 -1
  17. package/dist/lifecycle/member-ledger.d.ts +3 -2
  18. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  19. package/dist/lifecycle/plan-ledger.d.ts +114 -0
  20. package/dist/lifecycle/plan-ledger.d.ts.map +1 -0
  21. package/dist/lifecycle/work-lease.d.ts +140 -0
  22. package/dist/lifecycle/work-lease.d.ts.map +1 -0
  23. package/dist/op/activities/activity-contracts.d.ts +2 -2
  24. package/dist/op/builders.d.ts.map +1 -1
  25. package/dist/op/discover.d.ts +25 -0
  26. package/dist/op/discover.d.ts.map +1 -1
  27. package/dist/op/index.d.ts +9 -3
  28. package/dist/op/index.d.ts.map +1 -1
  29. package/dist/op/lifecycle-receipt-store.d.ts +34 -0
  30. package/dist/op/lifecycle-receipt-store.d.ts.map +1 -0
  31. package/dist/op/local-executor.d.ts +19 -0
  32. package/dist/op/local-executor.d.ts.map +1 -1
  33. package/dist/op/local-output.d.ts.map +1 -1
  34. package/dist/op/op-ir.d.ts +10 -1
  35. package/dist/op/op-ir.d.ts.map +1 -1
  36. package/dist/op/operator.d.ts +29 -0
  37. package/dist/op/operator.d.ts.map +1 -1
  38. package/dist/op/runtime.d.ts +9 -0
  39. package/dist/op/runtime.d.ts.map +1 -1
  40. package/dist/op/runtimes/local.d.ts.map +1 -1
  41. package/dist/op/step-output-ref.d.ts +2 -2
  42. package/dist/op/step-output-ref.d.ts.map +1 -1
  43. package/dist/op/steward.d.ts +140 -0
  44. package/dist/op/steward.d.ts.map +1 -0
  45. package/dist/op/types.d.ts +51 -0
  46. package/dist/op/types.d.ts.map +1 -1
  47. package/dist/op/work-lease-decl.d.ts +18 -0
  48. package/dist/op/work-lease-decl.d.ts.map +1 -0
  49. package/dist/op/work-lease-run.d.ts +173 -0
  50. package/dist/op/work-lease-run.d.ts.map +1 -0
  51. package/dist/workspace/box-isolation.d.ts +99 -0
  52. package/dist/workspace/box-isolation.d.ts.map +1 -0
  53. package/dist/workspace/checks/box-isolation.d.ts +18 -0
  54. package/dist/workspace/checks/box-isolation.d.ts.map +1 -0
  55. package/dist/workspace/checks/boxes.d.ts +71 -0
  56. package/dist/workspace/checks/boxes.d.ts.map +1 -0
  57. package/dist/workspace/checks/records.d.ts +1 -0
  58. package/dist/workspace/checks/records.d.ts.map +1 -1
  59. package/dist/workspace/checks.d.ts +10 -1
  60. package/dist/workspace/checks.d.ts.map +1 -1
  61. package/dist/workspace/decide.d.ts +184 -0
  62. package/dist/workspace/decide.d.ts.map +1 -0
  63. package/dist/workspace/decision-points.schema.json +137 -0
  64. package/dist/workspace/declaration.d.ts +51 -0
  65. package/dist/workspace/declaration.d.ts.map +1 -1
  66. package/dist/workspace/declaration.schema.json +172 -0
  67. package/dist/workspace/declared-kinds.d.ts +12 -0
  68. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  69. package/dist/workspace/points-cli.d.ts +113 -0
  70. package/dist/workspace/points-cli.d.ts.map +1 -0
  71. package/dist/workspace/points.d.ts +320 -0
  72. package/dist/workspace/points.d.ts.map +1 -0
  73. package/dist/workspace/reason-codes.d.ts +26 -0
  74. package/dist/workspace/reason-codes.d.ts.map +1 -1
  75. package/dist/workspace/record-assets.d.ts.map +1 -1
  76. package/dist/workspace/records-cli.d.ts +12 -0
  77. package/dist/workspace/records-cli.d.ts.map +1 -1
  78. package/dist/workspace/records.d.ts +8 -2
  79. package/dist/workspace/records.d.ts.map +1 -1
  80. package/dist/workspace/status-stewards.d.ts +121 -0
  81. package/dist/workspace/status-stewards.d.ts.map +1 -0
  82. package/dist/workspace/status.d.ts +52 -1
  83. package/dist/workspace/status.d.ts.map +1 -1
  84. package/dist/workspace/work-cli.d.ts +78 -0
  85. package/dist/workspace/work-cli.d.ts.map +1 -0
  86. package/package.json +1 -1
  87. package/src/cli/handlers/components.test.ts +93 -0
  88. package/src/cli/handlers/components.ts +44 -3
  89. package/src/cli/handlers/operator.ts +107 -2
  90. package/src/cli/handlers/run.test.ts +19 -0
  91. package/src/cli/handlers/run.ts +53 -1
  92. package/src/cli/main.test.ts +40 -0
  93. package/src/cli/main.ts +78 -2
  94. package/src/cli/mcp/workspace-tools.test.ts +14 -1
  95. package/src/cli/mcp/workspace-tools.ts +49 -5
  96. package/src/cli/registry.ts +31 -0
  97. package/src/components/verbs/vuln-scan.test.ts +124 -1
  98. package/src/components/verbs/vuln-scan.ts +142 -1
  99. package/src/lifecycle/git.ts +65 -15
  100. package/src/lifecycle/lease.test.ts +22 -0
  101. package/src/lifecycle/lease.ts +133 -29
  102. package/src/lifecycle/member-ledger.ts +3 -2
  103. package/src/lifecycle/plan-ledger.test.ts +148 -0
  104. package/src/lifecycle/plan-ledger.ts +158 -0
  105. package/src/lifecycle/work-lease.test.ts +236 -0
  106. package/src/lifecycle/work-lease.ts +426 -0
  107. package/src/op/builders.ts +5 -0
  108. package/src/op/discover.ts +71 -0
  109. package/src/op/index.ts +16 -3
  110. package/src/op/lifecycle-receipt-store.test.ts +60 -0
  111. package/src/op/lifecycle-receipt-store.ts +61 -0
  112. package/src/op/local-executor.ts +216 -18
  113. package/src/op/local-output.ts +13 -0
  114. package/src/op/op-ir.ts +14 -0
  115. package/src/op/operator.ts +75 -4
  116. package/src/op/runtime.ts +6 -0
  117. package/src/op/runtimes/local.ts +3 -0
  118. package/src/op/step-output-ref.ts +6 -2
  119. package/src/op/steward.test.ts +212 -0
  120. package/src/op/steward.ts +253 -0
  121. package/src/op/types.ts +53 -0
  122. package/src/op/work-lease-decl.ts +80 -0
  123. package/src/op/work-lease-run.test.ts +326 -0
  124. package/src/op/work-lease-run.ts +395 -0
  125. package/src/workspace/box-isolation.test.ts +261 -0
  126. package/src/workspace/box-isolation.ts +205 -0
  127. package/src/workspace/check-contract.test.ts +3 -1
  128. package/src/workspace/check.schema.json +15 -7
  129. package/src/workspace/checks/box-isolation.ts +68 -0
  130. package/src/workspace/checks/boxes.test.ts +197 -0
  131. package/src/workspace/checks/boxes.ts +307 -0
  132. package/src/workspace/checks/records.ts +25 -0
  133. package/src/workspace/checks.test.ts +7 -0
  134. package/src/workspace/checks.ts +19 -2
  135. package/src/workspace/decide.test.ts +224 -0
  136. package/src/workspace/decide.ts +576 -0
  137. package/src/workspace/decision-points.schema.json +137 -0
  138. package/src/workspace/declaration.schema.json +172 -0
  139. package/src/workspace/declaration.ts +137 -0
  140. package/src/workspace/declared-kinds.ts +25 -2
  141. package/src/workspace/intent.schema.json +4 -1
  142. package/src/workspace/point-answer.schema.json +95 -0
  143. package/src/workspace/points-cli.ts +273 -0
  144. package/src/workspace/points-write.schema.json +489 -0
  145. package/src/workspace/points.schema.json +710 -0
  146. package/src/workspace/points.test.ts +264 -0
  147. package/src/workspace/points.ts +564 -0
  148. package/src/workspace/read-contract.test.ts +18 -1
  149. package/src/workspace/reason-codes.test.ts +14 -1
  150. package/src/workspace/reason-codes.ts +33 -0
  151. package/src/workspace/record-assets.test.ts +3 -2
  152. package/src/workspace/record-assets.ts +4 -1
  153. package/src/workspace/records-cli.ts +15 -2
  154. package/src/workspace/records-contract.test.ts +3 -2
  155. package/src/workspace/records.schema.json +17 -0
  156. package/src/workspace/records.ts +33 -3
  157. package/src/workspace/status-contract.test.ts +178 -0
  158. package/src/workspace/status-stewards.ts +225 -0
  159. package/src/workspace/status.schema.json +230 -4
  160. package/src/workspace/status.ts +106 -5
  161. package/src/workspace/work-cli.test.ts +180 -0
  162. package/src/workspace/work-cli.ts +246 -0
  163. package/src/workspace/work-lease.schema.json +233 -0
  164. package/src/workspace/work-readiness-chud.test.ts +145 -0
@@ -56,6 +56,13 @@
56
56
  "$ref": "#/$defs/recordKind"
57
57
  }
58
58
  },
59
+ "hosts": {
60
+ "type": "array",
61
+ "description": "The hosts boxes run on (#2727). A host is one machine reached under one hostname: boxes on it share its ports, its state root and, in a browser, its cookie jar, so chant workspace check compares the boxes on one host and never boxes on different hosts. A member's box block names its host. Added in schema 1 by chant 0.91.0, so a declaration that uses it sets minReader to 0.91.0 or newer.",
62
+ "items": {
63
+ "$ref": "#/$defs/host"
64
+ }
65
+ },
59
66
  "checks": {
60
67
  "type": "object",
61
68
  "description": "Severity for the declaration checks that allow it, keyed by WSP id (#2535, ws-028): error, warning, info or off. chant workspace check refuses an id it does not know, and one whose severity is fixed.",
@@ -269,6 +276,9 @@
269
276
  "$ref": "#/$defs/recordKind"
270
277
  }
271
278
  },
279
+ "box": {
280
+ "$ref": "#/$defs/box"
281
+ },
272
282
  "upstream": {
273
283
  "type": "string",
274
284
  "minLength": 1,
@@ -354,6 +364,114 @@
354
364
  "description": "A file or directory path with / separators: no leading /, no . or .. segments and no trailing /.",
355
365
  "pattern": "^(?!\\.\\.?(/|$))[^/\\\\]+(/(?!\\.\\.?(/|$))[^/\\\\]+)*$"
356
366
  },
367
+ "box": {
368
+ "type": "object",
369
+ "description": "The member is a box, or holds a box's declarations (#2726). A box holds no credential: each capability it needs outside itself is reached through a broker, a runtime such as a lobby or a door, which holds the credential and enforces the scope. chant workspace check fails when a file in the member's directory carries a literal secret (WSP121) and when a capability names no broker (WSP122). chant workspace status --json lists the capabilities, so a broker can read the scopes. Its host, slot, ports, state and cookies state the box's isolation (#2727): chant derives each value from the box's identity, its host, the member's name and its slot, and prints them in chant workspace status --json, so a runtime reads them instead of choosing its own. chant workspace check fails when two boxes on a host resolve to the same value (WSP123) and when a box hard-codes a machine path (WSP124). Added in schema 1 by chant 0.91.0, so a declaration that uses it sets minReader to 0.91.0 or newer.",
370
+ "properties": {
371
+ "capabilities": {
372
+ "type": "array",
373
+ "description": "Each capability the box reaches outside itself, named once. None when omitted.",
374
+ "items": {
375
+ "$ref": "#/$defs/capability"
376
+ }
377
+ },
378
+ "host": {
379
+ "$ref": "#/$defs/name",
380
+ "description": "The host the box runs on, one of the top-level hosts (#2727). The box's name is the member's name."
381
+ },
382
+ "slot": {
383
+ "type": "integer",
384
+ "minimum": 0,
385
+ "description": "The box's number on its host (#2727). Its ports come from the slot's block of the host's range."
386
+ },
387
+ "ports": {
388
+ "type": "object",
389
+ "description": "The ports the box listens on, each a name and its offset in the box's block (#2727). The port is the block's first port plus the offset.",
390
+ "propertyNames": {
391
+ "$ref": "#/$defs/kindName"
392
+ },
393
+ "additionalProperties": {
394
+ "type": "integer",
395
+ "minimum": 0,
396
+ "maximum": 65534
397
+ }
398
+ },
399
+ "state": {
400
+ "type": "object",
401
+ "description": "State the box keeps outside its checkout, such as hud's identity and database, each a name and a path relative to the box's state directory (#2727). The name is usually the environment variable the runtime sets, such as HUD_IDENTITY_PATH. A path that is absolute, starts with ~ or an environment reference, or has a .. segment is a WSP124 finding.",
402
+ "propertyNames": {
403
+ "type": "string",
404
+ "pattern": "^[A-Za-z_][A-Za-z0-9_-]{0,63}$"
405
+ },
406
+ "additionalProperties": {
407
+ "type": "string",
408
+ "minLength": 1
409
+ }
410
+ },
411
+ "cookies": {
412
+ "type": "array",
413
+ "description": "Session cookie names the box's runtimes set, such as hud_session (#2727). A browser scopes a cookie to a host, not a port, so each resolves to <cookie>_<member name>.",
414
+ "uniqueItems": true,
415
+ "items": {
416
+ "type": "string",
417
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$"
418
+ }
419
+ }
420
+ },
421
+ "dependentRequired": {
422
+ "host": [
423
+ "slot"
424
+ ],
425
+ "slot": [
426
+ "host"
427
+ ],
428
+ "ports": [
429
+ "host"
430
+ ],
431
+ "state": [
432
+ "host"
433
+ ],
434
+ "cookies": [
435
+ "host"
436
+ ]
437
+ },
438
+ "patternProperties": {
439
+ "^x-": true
440
+ },
441
+ "additionalProperties": false
442
+ },
443
+ "capability": {
444
+ "type": "object",
445
+ "description": "A capability a box needs and does not hold the credential for, such as inference, fountain or a third-party API (#2726).",
446
+ "required": [
447
+ "name"
448
+ ],
449
+ "properties": {
450
+ "name": {
451
+ "$ref": "#/$defs/kindName",
452
+ "description": "The capability, such as inference or fountain. Unique within the box."
453
+ },
454
+ "broker": {
455
+ "type": "string",
456
+ "minLength": 1,
457
+ "description": "What brokers the capability: the runtime that holds the credential and swaps the box's own token for it, such as lobby or door. It may name a member of this workspace, or a runtime outside it. Without it the capability is unbrokered, and chant workspace check fails with WSP122."
458
+ },
459
+ "scope": {
460
+ "type": "array",
461
+ "uniqueItems": true,
462
+ "description": "What of the box's own the broker lets it reach, which the broker enforces. For Fountain: agent (start conversations with its own agent), vault (attach its own vault), conversations and sandboxes (its own). The words are the broker's; chant records them.",
463
+ "items": {
464
+ "type": "string",
465
+ "minLength": 1,
466
+ "pattern": "^[^\\u0000-\\u001f]+$"
467
+ }
468
+ }
469
+ },
470
+ "patternProperties": {
471
+ "^x-": true
472
+ },
473
+ "additionalProperties": false
474
+ },
357
475
  "recordKind": {
358
476
  "type": "object",
359
477
  "description": "A record kind the workspace declares (#2680): a kind file that exports recordKind. chant workspace check fails (WSP115) when the file is missing or does not load as a record kind.",
@@ -469,6 +587,60 @@
469
587
  "additionalProperties": false
470
588
  }
471
589
  ]
590
+ },
591
+ "host": {
592
+ "type": "object",
593
+ "description": "A host boxes run on (#2727).",
594
+ "required": [
595
+ "name",
596
+ "ports"
597
+ ],
598
+ "properties": {
599
+ "name": {
600
+ "$ref": "#/$defs/name",
601
+ "description": "The host's name, unique among hosts. A box block names it in host."
602
+ },
603
+ "ports": {
604
+ "type": "object",
605
+ "description": "The TCP ports boxes on this host take theirs from. Slot n owns the block from + n * perBox to from + (n + 1) * perBox - 1, which must end at or before to.",
606
+ "required": [
607
+ "from",
608
+ "to",
609
+ "perBox"
610
+ ],
611
+ "properties": {
612
+ "from": {
613
+ "$ref": "#/$defs/port",
614
+ "description": "The first port of the range."
615
+ },
616
+ "to": {
617
+ "$ref": "#/$defs/port",
618
+ "description": "The last port of the range, inclusive."
619
+ },
620
+ "perBox": {
621
+ "type": "integer",
622
+ "minimum": 1,
623
+ "maximum": 65535,
624
+ "description": "How many ports each box's block holds. A box's port offsets are below it."
625
+ }
626
+ },
627
+ "additionalProperties": false
628
+ },
629
+ "stateRoot": {
630
+ "type": "string",
631
+ "minLength": 1,
632
+ "description": "Where boxes on this host keep state, as an environment reference such as ${XDG_STATE_HOME}/chant/boxes, which the runtime expands on the machine. A box's state directory is <stateRoot>/<member name>. A literal machine path, such as /Users/... or anything under $HOME, is a WSP124 finding. Default ${XDG_STATE_HOME}/chant/boxes."
633
+ }
634
+ },
635
+ "patternProperties": {
636
+ "^x-": true
637
+ },
638
+ "additionalProperties": false
639
+ },
640
+ "port": {
641
+ "type": "integer",
642
+ "minimum": 1,
643
+ "maximum": 65535
472
644
  }
473
645
  }
474
646
  }
@@ -28,6 +28,18 @@ export interface DeclaredKind {
28
28
  code: DeclaredKindReasonCode;
29
29
  message: string;
30
30
  } | null;
31
+ /**
32
+ * For an answer kind (ws-058, #2738): its points file from the workspace
33
+ * root, and what is wrong with it, empty when nothing is. Absent for any
34
+ * other kind, and when the kind wasn't loaded.
35
+ */
36
+ points?: {
37
+ file: string;
38
+ problems: {
39
+ field: string | null;
40
+ message: string;
41
+ }[];
42
+ };
31
43
  }
32
44
  /** The kind file of `declared` on disk, under the workspace root `rootOnDisk`. */
33
45
  export declare function declaredKindFile(declared: RecordKindDeclaration, rootOnDisk: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"declared-kinds.d.ts","sourceRoot":"","sources":["../../src/workspace/declared-kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAuB,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,oHAAoH;AACpH,eAAO,MAAM,0BAA0B,yFAA0H,CAAC;AAClK,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAClE;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5F;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzB"}
1
+ {"version":3,"file":"declared-kinds.d.ts","sourceRoot":"","sources":["../../src/workspace/declared-kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAuB,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,oHAAoH;AACpH,eAAO,MAAM,0BAA0B,yFAA0H,CAAC;AAClK,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE;YAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;CAClF;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5F;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CA2BzB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * `chant workspace points [--open] [--kind <kind file>] [--at <rev>] [--json]`
3
+ * (ws-058, #2739): the workspace's decision points and the questions asked of
4
+ * them, a read-contract output (`points.schema.json`).
5
+ *
6
+ * The points come from each record kind the declaration names with an
7
+ * `answers` block, or from `--kind`, and the questions are that kind's
8
+ * records. A question is open while it is escalated to people or proposed by a
9
+ * model and not yet confirmed, and it lists any model's answer with its
10
+ * confidence, so a reader such as hud can prompt a person and an MCP client
11
+ * can see it. With `--open`, only open questions are listed. It never writes
12
+ * and never calls a model.
13
+ *
14
+ * `points ask` and `points answer` are the writes, in `decide.ts`.
15
+ */
16
+ import type { CommandContext } from "../cli/registry.js";
17
+ import { type ErrorLocation, type WorkspaceErrorCode } from "./declaration.js";
18
+ import { type QuestionView } from "./decide.js";
19
+ import { type Decider, type ModelAsk } from "./points.js";
20
+ export declare const POINTS_CONTRACT_VERSION = 1;
21
+ export declare const POINTS_OUTPUT_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/points/v1/points.schema.json";
22
+ /** Why `points` read nothing. Closed. */
23
+ export declare const POINTS_ERROR_CODES: readonly ["declaration-missing", "declaration-ambiguous", "declaration-unparseable", "declaration-invalid", "placement-invalid", "reader-too-old", "root-chant-required", "not-a-git-repository", "revision-unknown"];
24
+ /** Why one answer kind's points or questions could not be read. The document is still printed. Closed. */
25
+ export declare const POINTS_SOURCE_REASON_CODES: readonly ["kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "points-invalid"];
26
+ type SourceReasonCode = (typeof POINTS_SOURCE_REASON_CODES)[number];
27
+ /** One point as `points` lists it. */
28
+ export interface PointView {
29
+ name: string;
30
+ title: string;
31
+ /** The answer kind file, from the workspace root, whose records answer it. */
32
+ kind: string;
33
+ /** The points file, from the repository root. */
34
+ file: string;
35
+ /** sha256 of the declaration: a question asked under another version answers an older question. */
36
+ version: string;
37
+ questionType: string;
38
+ instructions: string;
39
+ candidates: (string | boolean)[];
40
+ /** Each input: its name, the read-contract output it names, and its description. */
41
+ inputs: {
42
+ name: string;
43
+ output: string;
44
+ description: string;
45
+ }[];
46
+ deciders: Decider[];
47
+ quorum: {
48
+ count: number;
49
+ roles?: string[];
50
+ };
51
+ }
52
+ /** One answer kind the read covered. */
53
+ export interface SourceView {
54
+ /** The kind file, as declared from the workspace root, or as given with --kind. */
55
+ kind: string;
56
+ /** The points file from the repository root, or null when the kind couldn't be loaded. */
57
+ points: string | null;
58
+ reason: {
59
+ code: SourceReasonCode;
60
+ message: string;
61
+ } | null;
62
+ }
63
+ export type PointsDocument = {
64
+ $schema: string;
65
+ contract: number;
66
+ chant: string;
67
+ at: string | null;
68
+ workspace: {
69
+ name: string;
70
+ root: string;
71
+ };
72
+ /** Whether only open questions are listed (--open). */
73
+ open: boolean;
74
+ sources: SourceView[];
75
+ points: PointView[];
76
+ questions: QuestionView[];
77
+ summary: {
78
+ points: number;
79
+ questions: number;
80
+ open: number;
81
+ escalated: number;
82
+ proposed: number;
83
+ answered: number;
84
+ };
85
+ } | {
86
+ $schema: string;
87
+ contract: number;
88
+ chant: string;
89
+ error: {
90
+ code: WorkspaceErrorCode;
91
+ message: string;
92
+ location: ErrorLocation | null;
93
+ };
94
+ };
95
+ export interface PointsQuery {
96
+ cwd: string;
97
+ at?: string;
98
+ open?: boolean;
99
+ /** One answer kind file, in place of the declared ones. */
100
+ kind?: string;
101
+ }
102
+ /** Read the points and questions. Never throws a read error: a declaration that can't be read is the failure document. */
103
+ export declare function workspacePoints(query: PointsQuery): Promise<PointsDocument>;
104
+ /** The document as lines for a person. */
105
+ export declare function formatPoints(doc: Extract<PointsDocument, {
106
+ points: unknown;
107
+ }>): string;
108
+ /** A POST /v1/systemone response the caller already has, as the model call: its answer to the point asked. */
109
+ export declare function responseAsk(response: unknown): ModelAsk;
110
+ /** `chant workspace points`, and its `ask` and `answer` verbs. */
111
+ export declare function runWorkspacePoints(ctx: CommandContext): Promise<number>;
112
+ export {};
113
+ //# sourceMappingURL=points-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"points-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/points-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Decision points (ws-058, #2738): the recurring questions a workspace asks of
3
+ * its own graph, declared as data, and the answers they leave (#2739).
4
+ *
5
+ * A points file is JSON, validated against `decision-points.schema.json`, and
6
+ * named by a record kind's `answers.points`: the kind whose records are the
7
+ * answers. Each point is a typed question (`noul`, `choice` or `score`, the
8
+ * question types of the POST /v1/systemone wire format, #2491), the inputs it
9
+ * reads, each named as a read-contract output, and an ordered chain of
10
+ * deciders:
11
+ *
12
+ * table rows of { when, answer }; the first row whose conditions all hold answers.
13
+ * model a backend asked the question with the inputs as its state, at a
14
+ * pinned model id. An answer at or above the threshold is a
15
+ * proposal a person confirms; below it, the next decider is asked.
16
+ * quorum people. Always last: the question escalates to them.
17
+ *
18
+ * chant never calls a model (ws-052). {@link runChain} takes the model call
19
+ * as a function, {@link ModelAsk}, which the decide Op activity (#2740), a
20
+ * runtime's decider or a test's stub supplies. Without one, a model decider is
21
+ * not asked and the chain moves on.
22
+ *
23
+ * Taken from chud's `packages/runtime/src/decide.mjs` at 43afcf1: the chain,
24
+ * the observation rule, the point version and the inputs hash. The records
25
+ * are chant records: `decide.ts` writes them, and {@link applyAnswers} warns
26
+ * about them on read.
27
+ */
28
+ import type { RecordSource } from "./record-source.js";
29
+ import type { LoadedRecordKind, ReadRecordsOptions, RecordEntry } from "./records.js";
30
+ export declare const DECISION_POINTS_SCHEMA_ID: string;
31
+ /**
32
+ * The read-contract outputs a point's input may name (#2738), each with the
33
+ * output schema and `$defs` entry that describes it. Closed: an input naming
34
+ * anything else is refused. `record`, `decision` and `work-item` are records
35
+ * as `records --json` lists them, of any kind, a decision kind and a work kind.
36
+ */
37
+ export declare const POINT_INPUT_OUTPUTS: {
38
+ readonly record: {
39
+ readonly schema: "records";
40
+ readonly def: "record";
41
+ readonly description: "a record of any kind, as records --json lists it";
42
+ };
43
+ readonly decision: {
44
+ readonly schema: "records";
45
+ readonly def: "record";
46
+ readonly description: "a decision record, as records --json lists it";
47
+ };
48
+ readonly "work-item": {
49
+ readonly schema: "records";
50
+ readonly def: "record";
51
+ readonly description: "a work item record, as records --json lists it (#2683)";
52
+ };
53
+ readonly finding: {
54
+ readonly schema: "intent";
55
+ readonly def: "finding";
56
+ readonly description: "a finding of graph --intent";
57
+ };
58
+ readonly region: {
59
+ readonly schema: "intent";
60
+ readonly def: "region";
61
+ readonly description: "the region an intent graph covers";
62
+ };
63
+ readonly commit: {
64
+ readonly schema: "intent";
65
+ readonly def: "commit";
66
+ readonly description: "a commit in an intent graph's window";
67
+ };
68
+ readonly member: {
69
+ readonly schema: "ls";
70
+ readonly def: "member";
71
+ readonly description: "a member, as ls lists it";
72
+ };
73
+ readonly gate: {
74
+ readonly schema: "status";
75
+ readonly def: "gate";
76
+ readonly description: "a gate, as status lists it";
77
+ };
78
+ readonly release: {
79
+ readonly schema: "status";
80
+ readonly def: "release";
81
+ readonly description: "a release, as status lists it; a release plan's fields until the lifecycle ledger lists plans (#2717)";
82
+ };
83
+ readonly environment: {
84
+ readonly schema: "status";
85
+ readonly def: "environment";
86
+ readonly description: "an environment, as status lists it";
87
+ };
88
+ readonly component: {
89
+ readonly schema: "composites";
90
+ readonly def: "component";
91
+ readonly description: "a component, as graph --composites lists it";
92
+ };
93
+ };
94
+ export type PointInputOutput = keyof typeof POINT_INPUT_OUTPUTS;
95
+ export declare const POINT_INPUT_OUTPUT_NAMES: PointInputOutput[];
96
+ /** The output an input name reads: the part before its first dot. */
97
+ export declare function inputOutput(name: string): string;
98
+ export type QuestionType = "noul" | "choice" | "score";
99
+ export interface Question {
100
+ /** `boolean` in a points file is read as `noul`. */
101
+ type: QuestionType;
102
+ instructions: string;
103
+ criteria: Record<string, string> | string[];
104
+ }
105
+ export type Scalar = string | number | boolean | null;
106
+ export type Condition = Scalar | {
107
+ eq?: Scalar;
108
+ ne?: Scalar;
109
+ lt?: number;
110
+ lte?: number;
111
+ gt?: number;
112
+ gte?: number;
113
+ in?: Scalar[];
114
+ };
115
+ export interface TableRow {
116
+ when: Record<string, Condition>;
117
+ answer: string | boolean;
118
+ note?: string;
119
+ }
120
+ export type Decider = {
121
+ kind: "table";
122
+ rows: TableRow[];
123
+ note?: string;
124
+ } | {
125
+ kind: "model";
126
+ backend: string;
127
+ model: string;
128
+ threshold: number;
129
+ unreachable?: "escalate" | "fail";
130
+ note?: string;
131
+ } | {
132
+ kind: "quorum";
133
+ count: number;
134
+ roles?: string[];
135
+ note?: string;
136
+ };
137
+ export interface Point {
138
+ title: string;
139
+ question: Question;
140
+ inputs: Record<string, string>;
141
+ deciders: Decider[];
142
+ }
143
+ /** One problem with a points file: the JSON path of the field, or null for the file, and what is wrong. */
144
+ export interface PointProblem {
145
+ field: string | null;
146
+ message: string;
147
+ }
148
+ export declare class PointsError extends Error {
149
+ readonly file: string;
150
+ readonly problems: PointProblem[];
151
+ constructor(file: string, problems: PointProblem[]);
152
+ }
153
+ /** A question's candidate answers: true and false, a choice's options, or a score's levels. */
154
+ export declare function candidates(question: Question): (string | boolean)[];
155
+ /** The schema's problems with `data`, as JSON paths. */
156
+ export declare function schemaProblems(data: unknown): PointProblem[];
157
+ /**
158
+ * Parse and validate a points file's text. Returns its points, with
159
+ * `boolean` read as `noul`. Throws a {@link PointsError} naming the file and
160
+ * each field.
161
+ */
162
+ export declare function parsePoints(text: string, file: string): Record<string, Point>;
163
+ /** One point by name, or undefined. */
164
+ export declare function pointOf(points: Record<string, Point>, name: string): Point | undefined;
165
+ /** JSON with keys sorted and undefined members left out, the text every hash here is taken over. */
166
+ export declare function canonical(value: unknown): string;
167
+ /** The version of a point: the sha256 of its declaration. Editing the question or any decider changes it. */
168
+ export declare const pointVersion: (point: Point) => string;
169
+ /** What is answered once: the point, its version and the inputs. */
170
+ export declare const inputsHash: (name: string, version: string, inputs: Record<string, unknown>) => string;
171
+ /** The id of the answer to `name` for inputs hashing to `hash`: the name and the hash's first 12 hex digits. */
172
+ export declare const answerId: (name: string, hash: string) => string;
173
+ /** The quorum a point ends in. */
174
+ export declare function quorumOf(point: Point): {
175
+ count: number;
176
+ roles?: string[];
177
+ };
178
+ /** Whether every condition in a row's `when` holds for these inputs. An input the state lacks never matches. */
179
+ export declare const matches: (when: Record<string, Condition>, inputs: Record<string, unknown>) => boolean;
180
+ /** A question as the POST /v1/systemone wire format asks it (#2491). */
181
+ export interface WireQuestion {
182
+ type: QuestionType;
183
+ instructions: string;
184
+ criteria: Record<string, string> | string[];
185
+ }
186
+ /** One answer in the wire format's shape. */
187
+ export type WireAnswer = {
188
+ type: "noul";
189
+ noul: number;
190
+ } | {
191
+ type: "choice";
192
+ choice: string;
193
+ probabilities?: Record<string, number>;
194
+ confidence?: number;
195
+ } | {
196
+ type: "score";
197
+ score?: number;
198
+ legend?: unknown;
199
+ probabilities?: Record<string, number>;
200
+ confidence?: number;
201
+ } | {
202
+ type: "unsupported";
203
+ };
204
+ export declare function wireQuestion(question: Question): WireQuestion;
205
+ /** What a model decider is asked. */
206
+ export interface ModelRequest {
207
+ point: string;
208
+ backend: string;
209
+ /** The pinned model id. */
210
+ model: string;
211
+ question: WireQuestion;
212
+ /** The inputs, as the state. */
213
+ state: Record<string, unknown>;
214
+ }
215
+ /**
216
+ * The model call, supplied by the caller: the decide Op activity (#2740), a
217
+ * runtime's decider, or a test's stub. It resolves with the model id that
218
+ * answered and one answer in the wire format's shape. Throwing means the
219
+ * backend could not be reached or gave nothing usable.
220
+ */
221
+ export type ModelAsk = (request: ModelRequest) => Promise<{
222
+ model: string;
223
+ answer: WireAnswer;
224
+ }>;
225
+ export type Observation = {
226
+ observed: true;
227
+ answer: string | boolean;
228
+ probabilities: Record<string, number>;
229
+ confidence: number;
230
+ } | {
231
+ observed: false;
232
+ answer?: string | boolean | null;
233
+ probabilities?: Record<string, number>;
234
+ confidence?: number;
235
+ reason: string;
236
+ };
237
+ /**
238
+ * A model's wire answer against the question and the decider's threshold
239
+ * (chud's rule):
240
+ *
241
+ * - noul p: true when p is at least the threshold, false when 1 - p is,
242
+ * otherwise not observed. Its confidence is max(p, 1 - p).
243
+ * - choice and score: the choice (a score's most probable level) when the
244
+ * reported confidence is at least the threshold. A backend that reports no
245
+ * confidence is read by its largest probability.
246
+ *
247
+ * An answer outside the candidates, or an unsupported question, is not observed.
248
+ */
249
+ export declare function observe(question: Question, answer: WireAnswer | undefined, threshold: number): Observation;
250
+ /** A decider that was asked and did not answer, and why. */
251
+ export interface Escalation {
252
+ kind: "table" | "model";
253
+ reason: string;
254
+ backend?: string;
255
+ model?: string;
256
+ answer?: string | boolean | null;
257
+ probabilities?: Record<string, number>;
258
+ confidence?: number;
259
+ threshold?: number;
260
+ }
261
+ export type ChainResult = {
262
+ status: "answered";
263
+ answer: string | boolean;
264
+ decider: {
265
+ kind: "table";
266
+ row: number;
267
+ };
268
+ note?: string;
269
+ escalations: Escalation[];
270
+ } | {
271
+ status: "proposed";
272
+ answer: string | boolean;
273
+ decider: {
274
+ kind: "model";
275
+ backend: string;
276
+ model: string;
277
+ };
278
+ probabilities: Record<string, number>;
279
+ confidence: number;
280
+ threshold: number;
281
+ escalations: Escalation[];
282
+ } | {
283
+ status: "escalated";
284
+ decider: {
285
+ kind: "quorum";
286
+ count: number;
287
+ roles?: string[];
288
+ };
289
+ escalations: Escalation[];
290
+ };
291
+ /** A model decider declared `unreachable: "fail"` could not answer, so the ask fails and nothing is written. */
292
+ export declare class DeciderFailed extends Error {
293
+ constructor(message: string);
294
+ }
295
+ /**
296
+ * Ask a point's deciders in order. A table row answers; a model at or above
297
+ * its threshold proposes; otherwise the question escalates to the quorum.
298
+ * Each decider that did not answer is in `escalations`, with why. A model
299
+ * decider is asked through `ask`; without it, it is not asked.
300
+ */
301
+ export declare function runChain(name: string, point: Point, inputs: Record<string, unknown>, ask?: ModelAsk): Promise<ChainResult>;
302
+ /** Why an answer record carries a warning. Closed, like the record warning codes. */
303
+ export declare const ANSWER_WARNING_CODES: readonly ["answer-points-unreadable", "answer-point-unknown", "answer-point-changed"];
304
+ export type AnswerWarningCode = (typeof ANSWER_WARNING_CODES)[number];
305
+ /** The points file an answer kind names, from `root` with / separators. */
306
+ export declare function pointsFileOf(loaded: LoadedRecordKind, root: string): string;
307
+ /** The points an answer kind names, read from `source` (the tree read), or the problems reading them. */
308
+ export declare function readPointsThrough(source: RecordSource, file: string): {
309
+ points: Record<string, Point>;
310
+ } | {
311
+ error: string;
312
+ problems: PointProblem[];
313
+ };
314
+ /**
315
+ * Give an answer kind's records their warnings, in place: the points file
316
+ * can't be read, the answer's point is gone, or the point changed since. They
317
+ * never make a record invalid.
318
+ */
319
+ export declare function applyAnswers(loaded: LoadedRecordKind, entries: RecordEntry[], options: ReadRecordsOptions): void;
320
+ //# sourceMappingURL=points.d.ts.map