@cratylus/canon 0.7.0 → 0.9.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 (92) hide show
  1. package/README.md +6 -4
  2. package/dist/agents/architect.js +2 -2
  3. package/dist/agents/architect.js.map +1 -1
  4. package/dist/agents/assayer.js +10 -10
  5. package/dist/agents/assayer.js.map +1 -1
  6. package/dist/agents/implementer.js +3 -3
  7. package/dist/agents/implementer.js.map +1 -1
  8. package/dist/agents/integrator.d.ts +2 -0
  9. package/dist/agents/integrator.js +18 -0
  10. package/dist/agents/integrator.js.map +1 -0
  11. package/dist/agents/kino.js +5 -4
  12. package/dist/agents/kino.js.map +1 -1
  13. package/dist/agents/mav.js +19 -37
  14. package/dist/agents/mav.js.map +1 -1
  15. package/dist/agents/nico.js +13 -31
  16. package/dist/agents/nico.js.map +1 -1
  17. package/dist/agents/planner.js +5 -5
  18. package/dist/agents/planner.js.map +1 -1
  19. package/dist/dimensions/actions/delegation.js +6 -1
  20. package/dist/dimensions/actions/delegation.js.map +1 -1
  21. package/dist/dimensions/engineering-principles/cold-decode-oracle.js +1 -1
  22. package/dist/dimensions/engineering-principles/cold-decode-oracle.js.map +1 -1
  23. package/dist/dimensions/engineering-principles/trust-but-verify.js +1 -1
  24. package/dist/dimensions/engineering-principles/trust-but-verify.js.map +1 -1
  25. package/dist/dimensions/objective/conceptual-integrity.d.ts +2 -0
  26. package/dist/dimensions/objective/conceptual-integrity.js +2 -0
  27. package/dist/dimensions/objective/conceptual-integrity.js.map +1 -0
  28. package/dist/dimensions/role/architect.js +5 -3
  29. package/dist/dimensions/role/architect.js.map +1 -1
  30. package/dist/dimensions/role/assayer.js +24 -13
  31. package/dist/dimensions/role/assayer.js.map +1 -1
  32. package/dist/dimensions/role/implementer.js +21 -4
  33. package/dist/dimensions/role/implementer.js.map +1 -1
  34. package/dist/dimensions/role/integrator.d.ts +2 -0
  35. package/dist/dimensions/role/integrator.js +27 -0
  36. package/dist/dimensions/role/integrator.js.map +1 -0
  37. package/dist/dimensions/role/planner.js +19 -7
  38. package/dist/dimensions/role/planner.js.map +1 -1
  39. package/dist/genus/prime-principle.d.ts +10 -0
  40. package/dist/genus/prime-principle.js +16 -0
  41. package/dist/genus/prime-principle.js.map +1 -0
  42. package/dist/hooks/deploy-drift-notice.js +9 -9
  43. package/dist/hooks/deploy-drift-notice.js.map +1 -1
  44. package/dist/hooks/purview-guardrail.js +134 -57
  45. package/dist/hooks/purview-guardrail.js.map +1 -1
  46. package/dist/hooks/stance-guardrail-pre.js +105 -42
  47. package/dist/hooks/stance-guardrail-pre.js.map +1 -1
  48. package/dist/hooks/stance-guardrail.js +161 -57
  49. package/dist/hooks/stance-guardrail.js.map +1 -1
  50. package/dist/index.js +1 -4
  51. package/dist/index.js.map +1 -1
  52. package/dist/manifest.d.ts +3 -2
  53. package/dist/manifest.js +6 -6
  54. package/dist/manifest.js.map +1 -1
  55. package/dist/roles/architect.js +27 -22
  56. package/dist/roles/architect.js.map +1 -1
  57. package/dist/roles/assayer.js +9 -7
  58. package/dist/roles/assayer.js.map +1 -1
  59. package/dist/roles/hold.d.ts +1 -1
  60. package/dist/roles/hold.js +5 -2
  61. package/dist/roles/hold.js.map +1 -1
  62. package/dist/roles/implementer.js +15 -5
  63. package/dist/roles/implementer.js.map +1 -1
  64. package/dist/roles/integrator.d.ts +2 -0
  65. package/dist/roles/integrator.js +51 -0
  66. package/dist/roles/integrator.js.map +1 -0
  67. package/dist/roles/planner.js +6 -5
  68. package/dist/roles/planner.js.map +1 -1
  69. package/dist/skills/create-skill/skill.js +2 -0
  70. package/dist/skills/create-skill/skill.js.map +1 -1
  71. package/dist/skills/deliver/skill.js +59 -130
  72. package/dist/skills/deliver/skill.js.map +1 -1
  73. package/dist/skills/design/skill.js +20 -10
  74. package/dist/skills/design/skill.js.map +1 -1
  75. package/dist/skills/exemplify/skill.js +2 -0
  76. package/dist/skills/exemplify/skill.js.map +1 -1
  77. package/dist/skills/formalize/skill.js +2 -0
  78. package/dist/skills/formalize/skill.js.map +1 -1
  79. package/dist/skills/introspect/skill.js +2 -0
  80. package/dist/skills/introspect/skill.js.map +1 -1
  81. package/dist/skills/materialize/skill.js +2 -0
  82. package/dist/skills/materialize/skill.js.map +1 -1
  83. package/dist/skills/plan/skill.js +30 -32
  84. package/dist/skills/plan/skill.js.map +1 -1
  85. package/dist/skills/probe/skill.js +2 -0
  86. package/dist/skills/probe/skill.js.map +1 -1
  87. package/dist/skills/signify/skill.js +2 -0
  88. package/dist/skills/signify/skill.js.map +1 -1
  89. package/package.json +4 -4
  90. package/dist/genus/founding-doctrine.d.ts +0 -7
  91. package/dist/genus/founding-doctrine.js +0 -13
  92. package/dist/genus/founding-doctrine.js.map +0 -1
@@ -1,12 +1,29 @@
1
1
  // The bottom arrow, and the only one that writes the substrate. `C ∉ implementer` is not
2
2
  // a deprivation: it is half of the two-description property that makes validation an
3
- // operation at all. An executor holding the design would be checking its own work
3
+ // operation at all. An implementer holding the design would be checking its own work
4
4
  // against its own terms, which is the closed loop the ladder exists to open.
5
- export const implementer = `implementer ≜ reads⟨spec · artifact⟩ → writes⟨artifact⟩
5
+ //
6
+ // WHAT LEAVES THIS POSITION IS THE ARTIFACT AND A NAME, NEVER AN ACCOUNT. The artifact is
7
+ // committed on the implementer's own branch and the return is `landed <unit> of <plan> at
8
+ // <commit>` or `blocked <unit> of <plan>: spec` and nothing else, so the layer above
9
+ // holds an address and nothing to be persuaded by. Acceptance rests on the assayer, who
10
+ // reads the shard and the files at that commit and never the spec or this position's
11
+ // words: a description of its own work handed up by the builder is one description
12
+ // judging itself, which is the closed loop again. What the implementer could not prove,
13
+ // and any finding it meets beside the path, is still owed to someone; it goes out as a
14
+ // note, the design's one channel for a delegate's finding, and not up through the return.
15
+ // A verdict of not achieved comes back to this same implementer, who amends the same
16
+ // unit.
17
+ export const implementer = `implementer ≜ reads⟨spec · artifact⟩ → writes⟨artifact · note⟩
6
18
  stratum ≜ intent ≺ C ≺ spec ≺ artifact ⟨≺ ≜ more-abstract-than · C ≜ durative-concept-lattice⟩
7
19
  C ∉ implementer ⟨holds spec ¬ design · TWO-descriptions ⇒ validate ≜ operation ¬ re-reading⟩
8
- reserves ⟨author(artifact) ↾ spec · verify ↾ spec-own-criteria⟩
20
+ builds ⟨ONE unit ↾ spec ALONE ¬ design⟩ ⟨own branch · commits own work⟩
21
+ reads(spec) ↦ \${cratylus plan show <unit> --plan <plan>} ⟨host-CLI⟩
22
+ reserves ⟨author(artifact) ↾ spec · verify ↾ spec-own-criteria⟩ ⟨proves ↾ spec-asked ∧ ¬ beyond⟩
9
23
  verify ⊥ validate ⟨validate ≜ conformance(C) · C ∉ implementer⟩
10
24
  exceeding ≜ work ≻ spec ⟨DEFECT ≅ falling-short ∧ subtler ∵ second-concept UNNAMED ⇒ UNCAUGHT downstream⟩
11
- spec ¬ buildable-as-written ⇒ SURFACED ¬ reinterpreted`;
25
+ spec ¬ buildable-as-written ⇒ SURFACED ¬ reinterpreted
26
+ returns ⟨name ∧ ¬ account⟩ ⟨landed⟨unit · plan · commit⟩ ∨ blocked⟨unit · plan · spec⟩⟩
27
+ judged ↦ assayer ⟨reads shard ∧ files@commit ¬ spec ¬ account⟩ · ¬achieved ⇒ findings ↦ SAME implementer ⇒ amends SAME unit
28
+ ¬proven ∨ finding-beside-path ↦ note ⟨¬ return⟩`;
12
29
  //# sourceMappingURL=implementer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"implementer.js","sourceRoot":"","sources":["../../../src/dimensions/role/implementer.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,qFAAqF;AACrF,kFAAkF;AAClF,6EAA6E;AAE7E,MAAM,CAAC,MAAM,WAAW,GAAS;;;;;;uDAMsB,CAAC"}
1
+ {"version":3,"file":"implementer.js","sourceRoot":"","sources":["../../../src/dimensions/role/implementer.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,qFAAqF;AACrF,qFAAqF;AACrF,6EAA6E;AAC7E,EAAE;AACF,0FAA0F;AAC1F,0FAA0F;AAC1F,qFAAqF;AACrF,wFAAwF;AACxF,qFAAqF;AACrF,mFAAmF;AACnF,wFAAwF;AACxF,uFAAuF;AACvF,0FAA0F;AAC1F,qFAAqF;AACrF,QAAQ;AAER,MAAM,CAAC,MAAM,WAAW,GAAS;;;;;;;;;;;gDAWe,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Role } from '../../manifest.js';
2
+ export declare const integrator: Role;
@@ -0,0 +1,27 @@
1
+ // THE ARROW THAT MAKES APPROVED WORK WHOLE, and the one whose codomain is not a layer of
2
+ // the ladder at all: it writes the LINE, the place approved work accumulates, and the
3
+ // commits that record the plan's state. Work reaches it already judged; what it adds is a
4
+ // fact no unit's own proof can carry, namely that the units still hold together. That is
5
+ // why the check runs here, once per combination, and never at an implementer or the
6
+ // assayer: a whole is a property of the combination, and a unit proven alone has proven
7
+ // nothing about it.
8
+ //
9
+ // `writes ≠ artifact` is the seam, and it is what the purview judge quotes. Combining is
10
+ // a git act and running the check is a check act, and both are reserved; an Edit or a
11
+ // Write to a source file is the artifact codomain, outside the arrow. A red is therefore
12
+ // a report and never a patch: repairing on the line would hand the architect an
13
+ // approved-looking whole nobody judged, and would make this position the builder its own
14
+ // gate is meant to be independent of.
15
+ //
16
+ // The four prohibitions after `reserves` are the cell. Judging is the assayer's (the
17
+ // verdict arrived before this position was reached), the design is the architect's, plan
18
+ // state is the planner's, and main is the operator's to receive: a release is a sign-off
19
+ // this position asks for and never takes.
20
+ export const integrator = `integrator ≜ reads⟨unit · commit · line⟩ → writes⟨line · commit ⟨records⟩⟩ ⟨unit ≜ assay-verdict achieved · line ≜ integration-line ⟨¬ main⟩⟩
21
+ stratum ≜ intent ≺ C ≺ spec ≺ artifact ⟨≺ ≜ more-abstract-than · C ≜ durative-concept-lattice⟩
22
+ takes ⟨unit ↾ achieved⟩ · ¬takes ⟨unit ¬ achieved⟩
23
+ reserves ⟨combine ⟨unit ⇒ line⟩ · whole-check ⟨project-full-check ↾ combined-tree · ONCE ∀ combination · ∄ check @ ⟨implementer ∨ assayer⟩⟩ · commit ⟨records ⟨plan · design · note⟩ ⟨written-since⟩ · pathspec · green⟩ · report ⟨green ↦ whole(unit) · red ∨ merge-conflict ↦ ⟨unit · failing-check⟩⟩ · ask ⟨operator ⇒ release(line → main)⟩ ⟨architect ↦ plan-close⟩⟩
24
+ red ∨ merge-conflict ⇒ line UNCHANGED ⟨report ↦ architect ↦ implementer(unit)⟩
25
+ writes ≠ artifact ⇒ ∄ write ⟨source · config⟩ @ integrator ⟨combine ≠ author · check ≠ repair⟩
26
+ ¬⟨repair · judge ⟨assay ∈ assayer⟩ · decide ⟨design ∈ architect · plan-state ∈ planner⟩ · move(main) ⟨release ≜ operator sign-off⟩⟩`;
27
+ //# sourceMappingURL=integrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrator.js","sourceRoot":"","sources":["../../../src/dimensions/role/integrator.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,sFAAsF;AACtF,0FAA0F;AAC1F,yFAAyF;AACzF,oFAAoF;AACpF,wFAAwF;AACxF,oBAAoB;AACpB,EAAE;AACF,yFAAyF;AACzF,sFAAsF;AACtF,yFAAyF;AACzF,gFAAgF;AAChF,yFAAyF;AACzF,sCAAsC;AACtC,EAAE;AACF,qFAAqF;AACrF,yFAAyF;AACzF,yFAAyF;AACzF,0CAA0C;AAE1C,MAAM,CAAC,MAAM,UAAU,GAAS;;;;;;oIAMoG,CAAC"}
@@ -3,12 +3,24 @@
3
3
  // while the work is bounded by where it is USED voids every disjointness proof the
4
4
  // waves rest on.
5
5
  //
6
- // `writes ≠ C` is the seam. A piece that will not decompose is surfaced intact, because
7
- // a planner permitted to redraw the boundary it was handed is the route by which the
8
- // design leaks back out into the work.
9
- export const planner = `planner ≜ reads⟨C · artifact⟩ → writes⟨spec⟩
6
+ // THE PLAN IS THIS ROLE'S, START TO END. It takes the shards the architect hands down,
7
+ // plans them, binds the plan when none is bound, moves each unit's state as work reaches
8
+ // it, closes the plan, and answers a stop by rectifying or rebuilding. What it returns to
9
+ // the architect is names and nothing else: the architect never reads behind a name, so a
10
+ // plan view or a spec that leaked upward would put the substrate back in the design-holder's
11
+ // hands.
12
+ //
13
+ // `writes ≠ C` is the seam. A shard that will not plan is surfaced intact, because a
14
+ // planner permitted to redraw the boundary it was handed is the route by which the
15
+ // design leaks back out into the work. The same seam runs the other way: when a shard
16
+ // the plan builds on is found wrong, the design is corrected by the architect and the
17
+ // plan is re-planned here; it is never the planner that changes the design.
18
+ export const planner = `planner ≜ reads⟨C · artifact⟩ → writes⟨spec · plan-records⟩
10
19
  stratum ≜ intent ≺ C ≺ spec ≺ artifact ⟨≺ ≜ more-abstract-than · C ≜ durative-concept-lattice⟩
11
- reserves ⟨census ⟨extant · references · resolved-by-use ¬ by-declaration⟩ · decompose ⟨cut-piece → MECE-units⟩ · realizes ⟨unit ⇀ anchor⟩ · sequence ⟨waves ⊨ disjoint-outputs⟩⟩
12
- writes ≠ C ⇒ cut-piece GIVEN ⟨boundary ¬ decomposable ⇒ SURFACED ¬ redrawn⟩
13
- writes ≠ artifact ⇒ ∄ build @ planner ⟨unit ≜ spec · executor builds⟩`;
20
+ plan-records ≜ ⟨unit · dependency · state · plan-state⟩
21
+ reserves ⟨census ⟨extant · references · resolved-by-use ¬ by-declaration⟩ · decompose ⟨shards ↦ MECE-units · unit ⇀ ONE shard · deps FIRST · effort(unit) ≤ capacity · how-per-harness ⟨plan-owned ¬ shard-owned⟩⟩ · realizes ⟨unit ⇀ anchor⟩ · sequence ⟨waves ⊨ disjoint-outputs⟩ · bind ⟨@ ratification ∧ ∄ plan-bound⟩ · record ⟨ready-unit ↦ active @ name-handed-out · unit ↦ completed @ whole⟩ · close ⟨∀ unit completed⟩ · rectify ∨ rebuild ⟨plan @ stop⟩ · reconcile ⟨plans ∧ units⟩⟩
22
+ returns ⟨plan-name ∧ ready-unit-names⟩ ∧ ¬ spec ∨ plan-view ⟨name ≜ address · architect ¬ reads behind⟩
23
+ state(unit) ∨ state(plan) moves ⊨ planner ⟨bind ∨ close ∨ advance · ∄ move @ implementer ∨ architect⟩
24
+ writes ≠ C ⇒ shard GIVEN ⟨shard ¬ plannable ⇒ SURFACED ¬ redrawn · wrong-shard ⇒ plan re-planned ¬ design changed⟩
25
+ writes ≠ artifact ⇒ ∄ build @ planner ⟨unit ≜ spec · implementer builds⟩`;
14
26
  //# sourceMappingURL=planner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/dimensions/role/planner.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,oFAAoF;AACpF,mFAAmF;AACnF,iBAAiB;AACjB,EAAE;AACF,wFAAwF;AACxF,qFAAqF;AACrF,uCAAuC;AAEvC,MAAM,CAAC,MAAM,OAAO,GAAS;;;;sEAIyC,CAAC"}
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/dimensions/role/planner.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,oFAAoF;AACpF,mFAAmF;AACnF,iBAAiB;AACjB,EAAE;AACF,uFAAuF;AACvF,yFAAyF;AACzF,0FAA0F;AAC1F,yFAAyF;AACzF,6FAA6F;AAC7F,SAAS;AACT,EAAE;AACF,qFAAqF;AACrF,mFAAmF;AACnF,sFAAsF;AACtF,sFAAsF;AACtF,4EAA4E;AAE5E,MAAM,CAAC,MAAM,OAAO,GAAS;;;;;;;yEAO4C,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The prime principle, as a leading `## Prime Principle` block emitted VERBATIM
3
+ * as the first section of a SKILL.md, set as `preamble` on exactly the skills
4
+ * whose laws apply it: those that name concepts by anchor, optimal sign or cold
5
+ * decode. An agent carries the axiom through its held role's
6
+ * engineering-principles, never through this block. The apex seed: the
7
+ * `cratylism` ground axiom + the intrinsic-carry clause, and nothing whose truth
8
+ * is contingent on this workspace.
9
+ */
10
+ export declare const primePrinciple: string;
@@ -0,0 +1,16 @@
1
+ import { cratylism } from '../dimensions/engineering-principles/cratylism.js';
2
+ /**
3
+ * The prime principle, as a leading `## Prime Principle` block emitted VERBATIM
4
+ * as the first section of a SKILL.md, set as `preamble` on exactly the skills
5
+ * whose laws apply it: those that name concepts by anchor, optimal sign or cold
6
+ * decode. An agent carries the axiom through its held role's
7
+ * engineering-principles, never through this block. The apex seed: the
8
+ * `cratylism` ground axiom + the intrinsic-carry clause, and nothing whose truth
9
+ * is contingent on this workspace.
10
+ */
11
+ export const primePrinciple = `## Prime Principle
12
+
13
+ ${cratylism}
14
+
15
+ intrinsic ⟨¬ ambient⟩`;
16
+ //# sourceMappingURL=prime-principle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prime-principle.js","sourceRoot":"","sources":["../../src/genus/prime-principle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mDAAmD,CAAC;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;EAE5B,SAAS;;sBAEW,CAAC"}
@@ -97,8 +97,8 @@
97
97
  // is held by a test rather than remembered.
98
98
  //
99
99
  // A FULL BYTE COMPARISON of every rendered artifact is therefore what runs — no
100
- // digest, and above all NO SAMPLE. A sampled check that misses the founding doctrine
101
- // reports "in sync", which is the exact failure this cell exists to end. The
100
+ // digest, and above all NO SAMPLE. A sample that skips the ten skills carrying the
101
+ // prime principle reports "in sync", which is the exact failure this cell exists to end. The
102
102
  // `deploy-drift-notice` suite re-measures the clean path and fails on a regression, so
103
103
  // the number above is a held bound rather than a remembered one.
104
104
  //
@@ -117,7 +117,7 @@
117
117
  // matches is now THIS harness's, because the projector substitutes this
118
118
  // harness's hooks-file name (`harness-hooks-file`) and its own name
119
119
  // (`harness-name`, passed to the comparator so it audits the right home). A
120
- // codex session reports on the codex deployment. The pair lives on
120
+ // omp session reports on the omp deployment. The pair lives on
121
121
  // `HarnessAdapter` and reaches here through projection, which is the only stage
122
122
  // that knows which adapter it is rendering for — the alternative was a
123
123
  // shell-side copy of the harness registry, a second home for adapter knowledge.
@@ -196,7 +196,7 @@ export const deployDriftNotice = {
196
196
  # - ADVISORY ONLY. Prints to stdout and exits 0. It never emits
197
197
  # {"decision":"block"} — a stale deployment must not block a session.
198
198
  # - NEVER SAMPLES. The comparison is the tool's own: whole tree, byte for byte.
199
- # A sampled check that misses the founding doctrine reports "in sync".
199
+ # A sample that skips the ten skills carrying the prime principle reports "in sync".
200
200
  # - NOT A COUNT. It relays the tool's report, which carries the superseded lines
201
201
  # still running and the rendered lines missing.
202
202
  #
@@ -229,9 +229,9 @@ DEPLOY_TOOL={{fact:deploy-bin}}
229
229
 
230
230
  # WHICH HARNESS THIS PROJECTION IS FOR. A hook worker is handed no identity by the
231
231
  # session it runs in, so a worker that must LOOK at a deployed tree had to guess —
232
- # and guessed claude, which made a codex session report on a sibling deployment.
232
+ # and guessed claude, which made an omp session report on a sibling deployment.
233
233
  # These two are the adapter's own \`name\` and \`hooksFile\`, substituted at
234
- # projection: the codex render of this cell carries codex's.
234
+ # projection: the omp render of this cell carries omp's.
235
235
  HARNESS={{fact:harness-name}}
236
236
  HARNESS_HOOKS_FILE={{fact:harness-hooks-file}}
237
237
 
@@ -283,8 +283,8 @@ done
283
283
  # A render tree is recognized by BEING one: \`agents/\` + \`skills/\` + THIS harness's
284
284
  # own hooks file. That file is what distinguishes this harness's tree from another
285
285
  # harness's tree sitting beside it, and it is named by projection rather than by
286
- # this script — so a codex render of this worker skips the claude tree and a claude
287
- # render skips the codex one. The \`--out\` dir is an operator's choice, so the tree
286
+ # this script — so an omp render of this worker skips the claude tree and a claude
287
+ # render skips the omp one. The \`--out\` dir is an operator's choice, so the tree
288
288
  # is discovered, never named.
289
289
  #
290
290
  # THE GLOB USED TO BE \`.render*\`, WHICH MADE THE PARAGRAPH ABOVE FALSE. The shape
@@ -376,7 +376,7 @@ if [ -z "$cli" ]; then
376
376
  fi
377
377
 
378
378
  # \`--harness\` is what makes the audited HOME this session's. Without it the tool
379
- # resolves its default root, so a codex tree would be compared against the claude
379
+ # resolves its default root, so an omp tree would be compared against the claude
380
380
  # deployment — a report that is about neither.
381
381
  # The tool reports and repairs nothing, so it is safe to point at a host mid-work.
382
382
  set +e
@@ -1 +1 @@
1
- {"version":3,"file":"deploy-drift-notice.js","sourceRoot":"","sources":["../../src/hooks/deploy-drift-notice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deploy-drift-notice.js","sourceRoot":"","sources":["../../src/hooks/deploy-drift-notice.ts"],"names":[],"mappings":"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"}
@@ -23,13 +23,15 @@
23
23
  // every agent in the corpus composed the fragment it claimed to enforce.
24
24
  //
25
25
  // WHAT IT BLOCKS is what the arrow excludes, and nothing else:
26
- // · a dispatch to a builder for a piece no planner decomposed, from a holder whose
27
- // arrow does not write spec — the architect skipping the middle rung;
26
+ // · a dispatch carrying a spec the dispatcher wrote, from a holder whose arrow does
27
+ // not write spec — the architect skipping the planner, who alone turns a shard into
28
+ // units;
28
29
  // · a write to the substrate by a holder whose arrow does not write artifact;
29
- // · a dispatch whose prompt is the operator's literal words rather than a cut piece
30
+ // · a dispatch whose prompt is the operator's literal words rather than a routed name
30
31
  // — the same dispatch-echo the stance guard catches at turn end, refused here
31
32
  // because at this moment the contract that convicts it is the ROLE's.
32
- // WHAT IT PASSES: a dispatch to a planner, a dispatch to an assayer, READING anything,
33
+ // WHAT IT PASSES: a dispatch to a planner, a dispatch routing a unit name to an
34
+ // implementer, a dispatch to an assayer, a dispatch to the integrator, READING anything,
33
35
  // and writing whatever the arrow reserves. Reading is never a block — the architect's
34
36
  // contract makes an artifact read a descent, but a read is cheap to undo and a gate
35
37
  // that fires on one would wedge every legitimate orientation.
@@ -40,8 +42,10 @@
40
42
  // error than a missed one.
41
43
  export const purviewGuardrail = {
42
44
  id: 'purview-guardrail',
43
- residue: 'structural-refusal ↾ mid-turn act ∉ role-arrow · deny-before-fire ⟨descent ⟨write(artifact) ∉ writes⟩ · skipped-rung ⟨dispatch(build) ∄ decomposition⟩ · dispatch-echo ⟨literal-words ≠ cut-piece⟩⟩ · pass ⟨read · act ∈ reserves · dispatch ↦ plan ∨ assay⟩ · law = the HOLDER-projected role-section ⟨quoted verbatim · ¬ authored-opinion⟩ · shared judge-backend ⟨sibling⟩ · fail-open ∧ evidence-checked ∧ re-entry-capped',
45
+ residue: 'structural-refusal ↾ mid-turn act ∉ role-arrow · deny-before-fire ⟨descent ⟨write(artifact) ∉ writes⟩ · skipped-rung ⟨dispatch(spec the dispatcher wrote) ∄ planner⟩ · dispatch-echo ⟨literal-words ≠ routed-name⟩⟩ · pass ⟨read · act ∈ reserves · dispatch ↦ plan ∨ implement(unit-name) ∨ assay ∨ integrate⟩ · law = the HOLDER-projected role-section ⟨quoted verbatim · ¬ authored-opinion⟩ · shared judge-backend ⟨sibling⟩ · fail-open ∧ evidence-checked ∧ re-entry-capped',
44
46
  substrate: 'harness',
47
+ // Bound by holding a role at all: the arrow it judges against is the role's own.
48
+ binds: { dimension: 'role' },
45
49
  order: 1,
46
50
  events: ['subagent.dispatch.pre', 'tool.use.pre'],
47
51
  entry: 'purview-guardrail.sh',
@@ -69,19 +73,82 @@ export const purviewGuardrail = {
69
73
  # - CONTRACT-ENROLLED, one step further. A persona whose Target carries no \`## Role\`
70
74
  # section has no arrow to be outside of, so it is allowed. A gate cannot convict
71
75
  # against a law that was never declared.
72
- # - FAILS OPEN. Any error (no jq, no Target, judge failure) -> exit 0.
76
+ # - FAILS OPEN, NEVER SILENTLY. Any error (no jq, no input, no Target, judge failure,
77
+ # unparseable verdict, unexpected error) -> exit 0, and the call goes through WITH A NOTICE
78
+ # the operator reads (\`say\`: Claude Code's JSON \`systemMessage\`, omp's relayed line) naming
79
+ # this guard and why it could not judge. Silence is reserved for "judged, pass", "not
80
+ # enrolled" and "no arrow declared".
73
81
  # - EVIDENCE-CHECKED. A BLOCK must quote a span that is literally present in the
74
- # payload; a citation that is not there is a fabricated block and is DISCARDED.
75
- # - LOOP-SAFE. A re-entry cap: never deny an identical tool_input twice.
82
+ # payload; a citation that is not there is a fabricated block and is DISCARDED — and the
83
+ # discard is said, since no verdict then stands.
84
+ # - LOOP-SAFE. A re-entry cap: never deny an identical tool_input twice. The second,
85
+ # identical call goes through unjudged, and says so.
76
86
  #
77
87
  # INPUT : Claude Code PreToolUse hook JSON on stdin.
78
88
  # OUTPUT : on a purview breach -> a deny decision on stdout + exit 0.
79
- # otherwise -> no stdout + exit 0.
89
+ # judged, pass -> no stdout + exit 0.
90
+ # let through with no verdict -> the notice \`say\` prints + exit 0.
80
91
  #
81
- # POSIX sh. Depends on: jq. Missing jq -> fail open.
92
+ # POSIX sh. Depends on: jq. Missing jq -> the guard says so and allows the call.
82
93
 
83
94
  set -eu
84
95
 
96
+ # WHAT AN OPERATOR READS WHEN THE GUARD CANNOT JUDGE, defined before anything that needs a
97
+ # command: the first thing that can be missing is \`jq\`, and a worker run with a PATH holding
98
+ # little beyond \`sh\` and \`cat\` must still say it did not judge, so \`esc\`, \`say\` and \`open\`
99
+ # are builtins only and nothing external runs above the jq check.
100
+ #
101
+ # Claude Code shows the operator a hook's JSON \`systemMessage\` and NOT its plain stdout on
102
+ # exit 0. omp's extension bridge reads the worker's plain stdout, and would relay a JSON object
103
+ # as raw JSON — hence one form per harness, chosen at projection by the harness's own name.
104
+ esc() {
105
+ _in="$1"
106
+ _out=""
107
+ _nl="$(printf '\\nx')"
108
+ _nl="\${_nl%x}"
109
+ _tab="$(printf '\\t')"
110
+ _cr="$(printf '\\r')"
111
+ while [ -n "$_in" ]; do
112
+ _rest="\${_in#?}"
113
+ _c="\${_in%"$_rest"}"
114
+ case "$_c" in
115
+ '\\') _c='\\\\' ;;
116
+ '"') _c='\\"' ;;
117
+ "$_nl") _c='\\n' ;;
118
+ "$_tab") _c='\\t' ;;
119
+ "$_cr") _c='\\r' ;;
120
+ esac
121
+ _out="$_out$_c"
122
+ _in="$_rest"
123
+ done
124
+ printf '%s' "$_out"
125
+ }
126
+ say() {
127
+ case "{{fact:harness-name}}" in
128
+ claude) printf '{"systemMessage":"%s"}\\n' "$(esc "$1")" ;;
129
+ *) printf '%s\\n' "$1" ;;
130
+ esac
131
+ }
132
+
133
+ allow() { exit 0; }
134
+
135
+ # A verdict and a failure are different facts and silence carries only one of them: \`allow\`
136
+ # means "judged, pass" or "not this guard's call", \`open\` means "could not judge" — the call
137
+ # still proceeds, and the operator is told.
138
+ open() {
139
+ [ -z "\${LOG:-}" ] || printf '%s\\n' "open: $1 tool=\${tool_name:-?} agent=\${agent_type:-?}" >> "$LOG" 2>/dev/null || true
140
+ say "PURVIEW GUARDRAIL — DARK: $1. This call was NOT judged; the absence of a deny is an absence of a verdict, not a clean one."
141
+ exit 0
142
+ }
143
+
144
+ # A PreToolUse hook must never break a session. An unexpected error (a nonzero status reaching
145
+ # the trap) is let through AND SAID; every deliberate \`exit 0\` arrives with status 0.
146
+ trap 'rc=$?; [ "$rc" -eq 0 ] || open "an unexpected error stopped it (exit status $rc)"; exit 0' EXIT
147
+
148
+ input="$(cat)"
149
+ [ -n "$input" ] || open "the hook received no input"
150
+ command -v jq >/dev/null 2>&1 || open "jq is not installed, so the hook payload cannot be read"
151
+
85
152
  # The sibling Stop hook's deployed dir owns the SHARED judge backend, resolved from
86
153
  # this script's own location exactly as the pre-hook resolves it — every hooks root
87
154
  # holds the hook dirs as siblings, so this derivation is true at every site this file
@@ -94,33 +161,32 @@ RUBRIC="\${PURVIEW_RUBRIC:-$NEUTRAL_ROOT/purview-guardrail/purview-judge-prompt.
94
161
  JUDGE_CMD="\${STANCE_JUDGE_CMD:-sh $JUDGE_DIR/stance-judge.sh}"
95
162
  LOG="\${PURVIEW_GUARD_LOG:-$SELF_DIR/misses.log}"
96
163
 
97
- trap 'exit 0' EXIT
98
-
99
- allow() { exit 0; }
100
- note() { printf '%s\\n' "$1" >> "$LOG" 2>/dev/null || true; }
101
-
102
- input="$(cat)"
103
- [ -n "$input" ] || allow
104
- command -v jq >/dev/null 2>&1 || allow
105
-
106
164
  cwd="$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null || true)"
107
165
  [ -n "$cwd" ] && cd "$cwd" 2>/dev/null || true
108
166
 
109
167
  # --- scope gate: the persona's OWN stance manifest -------------------------------------------
168
+ # The scope is the one the harness hands over: \`stance_scope\` where a dispatcher sits in the
169
+ # persona's own scope (omp), else the persona directory of the agent the payload NAMES
170
+ # (\`agent_type\`, Claude Code — none on a bare session) under this harness's home, one hop above
171
+ # the hooks root. Presence of the manifest is enrollment; no agent list lives here.
110
172
  stance_scope="$(printf '%s' "$input" | jq -r '.stance_scope // empty' 2>/dev/null || true)"
111
- [ -n "$stance_scope" ] || allow
112
- manifest="$stance_scope/stance/manifest.json"
173
+ if [ -z "$stance_scope" ]; then
174
+ named="$(printf '%s' "$input" | jq -r '.agent_type // empty' 2>/dev/null || true)"
175
+ case "$named" in '' | */* | . | ..) allow ;; esac
176
+ stance_scope="$(dirname -- "$HOOKS_ROOT")/{{fact:harness-persona-root}}/$named"
177
+ fi
178
+ manifest="$stance_scope/{{fact:stance-manifest}}"
113
179
  [ -f "$manifest" ] || allow
114
180
  agent_type="$(jq -r '.agent // empty' "$manifest" 2>/dev/null || true)"
115
- [ -n "$agent_type" ] || allow
181
+ [ -n "$agent_type" ] || open "the stance manifest at $manifest names no agent, so there is no declared contract to judge against"
116
182
 
117
183
  # --- the LAW: this persona's own projected role contract -------------------------------------
118
- # A persona scope is \`<root>/agent/personas/<name>\` and the Target it was projected
119
- # from is \`<root>/agent/agents/<name>.md\` — two levels out and back down, the same
120
- # shape of derivation the judge path above uses. Overridable for test rigs.
184
+ # A persona scope is \`<root>/personas/<name>\` (claude) or \`<root>/agent/personas/<name>\` (omp), and
185
+ # the Target it was projected from is \`agents/<name>.md\` beside \`personas/\` — two levels out and
186
+ # back down, the same shape of derivation the judge path above uses. Overridable for test rigs.
121
187
  AGENT_ROOT="$(dirname -- "$(dirname -- "$stance_scope")")"
122
188
  AGENT_MD="\${PURVIEW_AGENT_MD:-$AGENT_ROOT/agents/$agent_type.md}"
123
- [ -f "$AGENT_MD" ] || allow
189
+ [ -f "$AGENT_MD" ] || open "the agent's projected Target is not at $AGENT_MD, so its declared contract cannot be read"
124
190
  contract="$(awk '/^## Role$/{f=1;next} /^## /{f=0} f' "$AGENT_MD" 2>/dev/null || true)"
125
191
  # A contract that is a BARE TOKEN states no arrow, so there is nothing to be outside
126
192
  # of. Only a multi-line contract is scoreable, and saying so here is what keeps the
@@ -129,13 +195,13 @@ contract="$(awk '/^## Role$/{f=1;next} /^## /{f=0} f' "$AGENT_MD" 2>/dev/null ||
129
195
 
130
196
  # --- extract the judged payload, branched by act ---------------------------------------------
131
197
  tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null || true)"
132
- [ -n "$tool_name" ] || allow
198
+ [ -n "$tool_name" ] || open "the payload names no tool, so there is no call to judge"
133
199
 
134
200
  case "$tool_name" in
135
201
  Agent|SendMessage|Task)
136
202
  body="$(printf '%s' "$input" | jq -r '.tool_input.prompt // .tool_input.message // .tool_input.description // ""' 2>/dev/null || true)"
137
203
  target="$(printf '%s' "$input" | jq -r '.tool_input.subagent_type // .tool_input.agent // .tool_input.name // ""' 2>/dev/null || true)"
138
- act="DISPATCH to \\\`\${target:-unnamed}\\\` (codomain: the spec this delegate will build from)"
204
+ act="DISPATCH to \\\`\${target:-unnamed}\\\` (codomain: route when it carries a unit name and address only, spec when it carries instructions the dispatcher wrote)"
139
205
  ;;
140
206
  Write|Edit|MultiEdit|NotebookEdit)
141
207
  body="$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.path // .tool_input.notebook_path // ""' 2>/dev/null || true)"
@@ -160,28 +226,32 @@ $body"
160
226
  session_id="$(printf '%s' "$input" | jq -r '.session_id // "nosession"' 2>/dev/null || echo nosession)"
161
227
  sig="$(printf '%s' "$input" | jq -c '.tool_input' 2>/dev/null | cksum | cut -d' ' -f1 2>/dev/null || echo 0)"
162
228
  seen="\${TMPDIR:-/tmp}/.purview-pre-$session_id-$sig"
163
- [ -f "$seen" ] && allow
229
+ [ -f "$seen" ] && open "this exact call was already denied once, so the re-entry cap lets it through unjudged"
164
230
 
165
231
  # --- judge (SHARED backend, OWN rubric) -----------------------------------------------------
166
- if [ -n "\${PURVIEW_EMIT_PAYLOAD:-}" ]; then
232
+ # THE SAME SEAM, UNDER THE SAME NAMES, as the two stance workers: a host that holds a model
233
+ # runs this worker twice around a judgment it makes itself (\`STANCE_EMIT_PAYLOAD\` to receive
234
+ # the payload and rubric, \`STANCE_VERDICT_FILE\` naming the answer). This one read
235
+ # \`PURVIEW_\`-prefixed names of its own, so the omp bridge — which speaks the shared names —
236
+ # got no payload back and purview judged nothing there, on every call, while reading as a
237
+ # guard that had found nothing.
238
+ if [ -n "\${STANCE_EMIT_PAYLOAD:-}" ]; then
167
239
  jq -cn --arg r "$RUBRIC" --arg p "$payload" '{rubric:$r, payload:$p}'
168
240
  exit 0
169
241
  fi
170
- if [ -n "\${PURVIEW_VERDICT_FILE:-}" ]; then
171
- verdict="$(cat "\${PURVIEW_VERDICT_FILE}" 2>/dev/null || true)"
172
- [ -n "$verdict" ] || {
173
- note "$(date -u +%Y-%m-%dT%H:%M:%SZ) judge-empty tool=$tool_name agent=$agent_type"
174
- allow
175
- }
242
+ if [ -n "\${STANCE_VERDICT_FILE:-}" ]; then
243
+ verdict="$(cat "\${STANCE_VERDICT_FILE}" 2>/dev/null || true)"
244
+ [ -n "$verdict" ] || open "the judge did not answer"
176
245
  else
177
- verdict="$(printf '%s' "$payload" | $JUDGE_CMD "$RUBRIC" 2>/dev/null)" || {
178
- note "$(date -u +%Y-%m-%dT%H:%M:%SZ) judge-fail tool=$tool_name agent=$agent_type"
179
- allow
180
- }
246
+ verdict="$(printf '%s' "$payload" | $JUDGE_CMD "$RUBRIC" 2>/dev/null)" || open "the judge did not answer"
181
247
  fi
182
248
 
183
- decision="$(printf '%s\\n' "$verdict" | sed -n 's/^VERDICT:[[:space:]]*//p' | head -1)"
184
- [ "$decision" = "BLOCK" ] || allow
249
+ decision="$(printf '%s\\n' "$verdict" | sed -n 's/^VERDICT:[[:space:]]*//p' | head -1 | sed 's/[[:space:]]*$//')"
250
+ case "$decision" in
251
+ PASS) allow ;; # judged, pass: the one silent verdict
252
+ BLOCK) ;;
253
+ *) open "the judge's verdict was unparseable (no VERDICT: PASS or VERDICT: BLOCK line)" ;;
254
+ esac
185
255
 
186
256
  reason="$(printf '%s\\n' "$verdict" | sed -n 's/^REASON:[[:space:]]*//p' | head -1)"
187
257
  [ -n "$reason" ] || reason="This act falls outside the arrow your role contract declares."
@@ -193,8 +263,9 @@ reason="$(printf '%s\\n' "$verdict" | sed -n 's/^REASON:[[:space:]]*//p' | head
193
263
  cited="$(printf '%s\\n' "$verdict" | sed -n 's/^SPAN:[[:space:]]*//p' | head -1)"
194
264
  if [ -n "$cited" ]; then
195
265
  printf '%s' "$payload" | grep -qF -- "$cited" || {
196
- note "$(date -u +%Y-%m-%dT%H:%M:%SZ) evidence-fail tool=$tool_name agent=$agent_type span=$cited"
197
- allow
266
+ [ -z "\${LOG:-}" ] || printf '%s\\n' "block-discarded: span=$cited tool=$tool_name agent=$agent_type" >> "$LOG" 2>/dev/null || true
267
+ say "PURVIEW GUARDRAIL — BLOCK DISCARDED: the judge blocked this call but cited a span that is not in it (fabricated): $cited. No verdict stands; this call was NOT judged clean."
268
+ exit 0
198
269
  }
199
270
  fi
200
271
 
@@ -202,10 +273,11 @@ fi
202
273
 
203
274
  feedback="PURVIEW GUARDRAIL — denied this $tool_name call: it falls outside the arrow your own \\
204
275
  role contract declares. $reason Delegation is a THEOREM of that arrow, not an option: an act whose \\
205
- domain or codomain lies outside it goes to the role that owns it — a decomposition to a planner, a \\
206
- build to an implementer, an artifact reading to an assayer. Hand it over and carry on with what the \\
207
- contract reserves. (Legitimate and NOT blocked here: reading anything, dispatching to a planner or an \\
208
- assayer, and performing any act the contract's own \\\`reserves\\\` clause names.)"
276
+ domain or codomain lies outside it goes to the role that owns it — a decomposition of a shard to a \\
277
+ planner, a build to an implementer, an artifact reading to an assayer, a merge or a whole check to \\
278
+ the integrator. Hand it over by name and carry on with what the contract reserves. (Legitimate and \\
279
+ NOT blocked here: reading anything, dispatching to a planner, routing a unit name to an implementer, \\
280
+ an assayer or the integrator, and performing any act the contract's own \\\`reserves\\\` clause names.)"
209
281
 
210
282
  jq -cn --arg r "$feedback" '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:$r}}'
211
283
  exit 0
@@ -251,7 +323,9 @@ durative concept lattice — the design.
251
323
 
252
324
  An act has a **domain** (the layer it consumes) and a **codomain** (the layer it produces):
253
325
 
254
- - a DISPATCH produces a **spec** — the delegate's instructions are the layer being written;
326
+ - a DISPATCH that carries a unit name and its address only produces a **route**; a DISPATCH that
327
+ carries instructions the dispatcher wrote produces a **spec** — those instructions are the layer
328
+ being written;
255
329
  - a WRITE to a source or config file produces an **artifact**;
256
330
  - reading anything at all produces **nothing**, and is never a breach.
257
331
 
@@ -263,20 +337,23 @@ whole test, and it is mechanical.
263
337
  - **A write whose codomain is \`artifact\` by a holder whose \`writes\` set excludes \`artifact\`.**
264
338
  The contract usually names this: \`descent\`. The path in the payload is the evidence.
265
339
  - **A dispatch whose codomain is \`spec\` by a holder whose \`writes\` set excludes \`spec\`.** This is
266
- the skipped rung: a holder that writes only the design has handed a delegate a spec that no
267
- spec-writing role produced. The prompt is the evidence.
268
- - **A dispatch whose prompt is the operator's literal words rather than a piece the agent cut.** The
269
- contract that convicts this is the same clause: a dispatch is a spec, and transcription is not
270
- authorship. Evidence is the prompt reading as relayed instructions rather than a bounded piece
271
- with its own acceptance.
340
+ the skipped rung: a holder that writes only the design and its routes has handed a delegate
341
+ instructions it wrote itself, where only a planner turns a shard into units. The prompt is the
342
+ evidence.
343
+ - **A dispatch whose prompt is the operator's literal words rather than a routed name.** The
344
+ contract that convicts this is the same clause: transcription is not authorship, and a dispatch
345
+ carries a name, not instructions. Evidence is the prompt reading as relayed instructions rather
346
+ than a unit name with its address.
272
347
 
273
348
  ## What to PASS — and these are the majority
274
349
 
275
350
  - **Any read.** Reading is outside the test by construction. Even where a contract calls
276
351
  artifact-reading a descent, that is a standing discipline, not a mid-turn refusal.
277
352
  - **A dispatch to a role the contract explicitly routes to.** Contracts name their delegations
278
- (\`⟨C → spec⟩ ↦ plan\`, \`⟨artifact → C⟩ ↦ assay\`). Handing work to a named delegate is the arrow
279
- WORKING.
353
+ (\`⟨C → spec⟩ ↦ planner\`, \`⟨spec → artifact⟩ ↦ implementer\`, \`⟨artifact → C⟩ ↦ assayer\`, the
354
+ integrator for gate, merge and record). A dispatch to a planner, a dispatch routing a unit name
355
+ to an implementer, a dispatch to an assayer and a dispatch to the integrator are the arrow
356
+ WORKING, whether the contract's \`writes\` names \`route\` or not.
280
357
  - **Any act the \`reserves\` clause names**, whatever it is.
281
358
  - **A write by a holder whose \`writes\` set includes \`artifact\`.** Most agents in most corpora
282
359
  build. Do not read a contract's other clauses as narrowing an arrow that plainly permits the act.
@@ -1 +1 @@
1
- {"version":3,"file":"purview-guardrail.js","sourceRoot":"","sources":["../../src/hooks/purview-guardrail.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,EAAE;AACF,oEAAoE;AACpE,oFAAoF;AACpF,mFAAmF;AACnF,kFAAkF;AAClF,qBAAqB;AACrB,EAAE;AACF,iFAAiF;AACjF,uFAAuF;AACvF,uFAAuF;AACvF,uFAAuF;AACvF,mFAAmF;AACnF,wFAAwF;AACxF,EAAE;AACF,sFAAsF;AACtF,oFAAoF;AACpF,uFAAuF;AACvF,uFAAuF;AACvF,uFAAuF;AACvF,+EAA+E;AAC/E,sFAAsF;AACtF,yEAAyE;AACzE,EAAE;AACF,+DAA+D;AAC/D,qFAAqF;AACrF,0EAA0E;AAC1E,gFAAgF;AAChF,sFAAsF;AACtF,kFAAkF;AAClF,0EAA0E;AAC1E,uFAAuF;AACvF,sFAAsF;AACtF,oFAAoF;AACpF,8DAA8D;AAC9D,EAAE;AACF,sFAAsF;AACtF,wFAAwF;AACxF,mFAAmF;AACnF,2BAA2B;AAE3B,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,EAAE,EAAE,mBAAmB;IACvB,OAAO,EACL,iaAAia;IACna,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,uBAAuB,EAAE,cAAc,CAAC;IACjD,KAAK,EAAE,sBAAsB;IAC7B,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,sBAAsB;YAChC,UAAU,EAAE,uDAAuD;YACnE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Jd;SACI;QACD;YACE,QAAQ,EAAE,yBAAyB;YACnC,UAAU,EAAE,0DAA0D;YACtE,UAAU,EAAE,KAAK;YACjB,iFAAiF;YACjF,2EAA2E;YAC3E,6EAA6E;YAC7E,8EAA8E;YAC9E,6BAA6B;YAC7B,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Ed;SACI;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"purview-guardrail.js","sourceRoot":"","sources":["../../src/hooks/purview-guardrail.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,EAAE;AACF,oEAAoE;AACpE,oFAAoF;AACpF,mFAAmF;AACnF,kFAAkF;AAClF,qBAAqB;AACrB,EAAE;AACF,iFAAiF;AACjF,uFAAuF;AACvF,uFAAuF;AACvF,uFAAuF;AACvF,mFAAmF;AACnF,wFAAwF;AACxF,EAAE;AACF,sFAAsF;AACtF,oFAAoF;AACpF,uFAAuF;AACvF,uFAAuF;AACvF,uFAAuF;AACvF,+EAA+E;AAC/E,sFAAsF;AACtF,yEAAyE;AACzE,EAAE;AACF,+DAA+D;AAC/D,sFAAsF;AACtF,wFAAwF;AACxF,aAAa;AACb,gFAAgF;AAChF,wFAAwF;AACxF,kFAAkF;AAClF,0EAA0E;AAC1E,gFAAgF;AAChF,yFAAyF;AACzF,sFAAsF;AACtF,oFAAoF;AACpF,8DAA8D;AAC9D,EAAE;AACF,sFAAsF;AACtF,wFAAwF;AACxF,mFAAmF;AACnF,2BAA2B;AAE3B,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,EAAE,EAAE,mBAAmB;IACvB,OAAO,EACL,odAAod;IACtd,SAAS,EAAE,SAAS;IACpB,iFAAiF;IACjF,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;IAC5B,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,uBAAuB,EAAE,cAAc,CAAC;IACjD,KAAK,EAAE,sBAAsB;IAC7B,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,sBAAsB;YAChC,UAAU,EAAE,uDAAuD;YACnE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiOd;SACI;QACD;YACE,QAAQ,EAAE,yBAAyB;YACnC,UAAU,EAAE,0DAA0D;YACtE,UAAU,EAAE,KAAK;YACjB,iFAAiF;YACjF,2EAA2E;YAC3E,6EAA6E;YAC7E,8EAA8E;YAC9E,6BAA6B;YAC7B,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Ed;SACI;KACF;CACF,CAAC"}