@monoes/monomindcli 2.12.0 → 2.14.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 (185) hide show
  1. package/.claude/skills/mastermind/SKILL.md +1 -15
  2. package/README.md +1 -1
  3. package/dist/src/commands/doctor-mcp-probe.d.ts +48 -0
  4. package/dist/src/commands/doctor-mcp-probe.d.ts.map +1 -0
  5. package/dist/src/commands/doctor-mcp-probe.js +205 -0
  6. package/dist/src/commands/doctor-mcp-probe.js.map +1 -0
  7. package/dist/src/commands/doctor-monoes-checks.d.ts +1 -0
  8. package/dist/src/commands/doctor-monoes-checks.d.ts.map +1 -1
  9. package/dist/src/commands/doctor-monoes-checks.js +96 -34
  10. package/dist/src/commands/doctor-monoes-checks.js.map +1 -1
  11. package/dist/src/commands/doctor-project-checks.d.ts +31 -1
  12. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  13. package/dist/src/commands/doctor-project-checks.js +109 -4
  14. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  15. package/dist/src/commands/doctor.d.ts.map +1 -1
  16. package/dist/src/commands/doctor.js +21 -3
  17. package/dist/src/commands/doctor.js.map +1 -1
  18. package/dist/src/commands/init.d.ts.map +1 -1
  19. package/dist/src/commands/init.js +29 -0
  20. package/dist/src/commands/init.js.map +1 -1
  21. package/dist/src/commands/mcp.d.ts.map +1 -1
  22. package/dist/src/commands/mcp.js +4 -3
  23. package/dist/src/commands/mcp.js.map +1 -1
  24. package/dist/src/commands/org-observe.d.ts.map +1 -1
  25. package/dist/src/commands/org-observe.js +14 -0
  26. package/dist/src/commands/org-observe.js.map +1 -1
  27. package/dist/src/commands/org.d.ts.map +1 -1
  28. package/dist/src/commands/org.js +21 -4
  29. package/dist/src/commands/org.js.map +1 -1
  30. package/dist/src/commands/ui.d.ts.map +1 -1
  31. package/dist/src/commands/ui.js +4 -0
  32. package/dist/src/commands/ui.js.map +1 -1
  33. package/dist/src/init/claudemd-generator.d.ts.map +1 -1
  34. package/dist/src/init/claudemd-generator.js +2 -1
  35. package/dist/src/init/claudemd-generator.js.map +1 -1
  36. package/dist/src/init/copy-assets.d.ts.map +1 -1
  37. package/dist/src/init/copy-assets.js +56 -18
  38. package/dist/src/init/copy-assets.js.map +1 -1
  39. package/dist/src/init/executor.d.ts.map +1 -1
  40. package/dist/src/init/executor.js +9 -1
  41. package/dist/src/init/executor.js.map +1 -1
  42. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  43. package/dist/src/init/mcp-generator.js +3 -3
  44. package/dist/src/init/mcp-generator.js.map +1 -1
  45. package/dist/src/init/never-commit.d.ts +39 -0
  46. package/dist/src/init/never-commit.d.ts.map +1 -0
  47. package/dist/src/init/never-commit.js +15 -0
  48. package/dist/src/init/never-commit.js.map +1 -0
  49. package/dist/src/init/shared.d.ts +74 -1
  50. package/dist/src/init/shared.d.ts.map +1 -1
  51. package/dist/src/init/shared.js +166 -0
  52. package/dist/src/init/shared.js.map +1 -1
  53. package/dist/src/init/types.d.ts +11 -0
  54. package/dist/src/init/types.d.ts.map +1 -1
  55. package/dist/src/init/types.js.map +1 -1
  56. package/dist/src/init/upgrade.d.ts.map +1 -1
  57. package/dist/src/init/upgrade.js +1 -0
  58. package/dist/src/init/upgrade.js.map +1 -1
  59. package/dist/src/init/write-kimicode.d.ts.map +1 -1
  60. package/dist/src/init/write-kimicode.js +13 -9
  61. package/dist/src/init/write-kimicode.js.map +1 -1
  62. package/dist/src/init/write-opencode.d.ts.map +1 -1
  63. package/dist/src/init/write-opencode.js +44 -2
  64. package/dist/src/init/write-opencode.js.map +1 -1
  65. package/dist/src/init/write-runtime-config.d.ts +2 -0
  66. package/dist/src/init/write-runtime-config.d.ts.map +1 -1
  67. package/dist/src/init/write-runtime-config.js +65 -38
  68. package/dist/src/init/write-runtime-config.js.map +1 -1
  69. package/dist/src/mastermind/manifest-data.d.ts.map +1 -1
  70. package/dist/src/mastermind/manifest-data.js +14 -0
  71. package/dist/src/mastermind/manifest-data.js.map +1 -1
  72. package/dist/src/mcp/monoes-mcp-entry.mjs +86 -0
  73. package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -1
  74. package/dist/src/mcp-tools/terminal-tools.js +52 -9
  75. package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
  76. package/dist/src/memory/memory-bridge.d.ts +84 -3
  77. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  78. package/dist/src/memory/memory-bridge.js +215 -17
  79. package/dist/src/memory/memory-bridge.js.map +1 -1
  80. package/dist/src/orgrt/agent-runner.d.ts +38 -0
  81. package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
  82. package/dist/src/orgrt/agent-runner.js +47 -0
  83. package/dist/src/orgrt/agent-runner.js.map +1 -1
  84. package/dist/src/orgrt/checkpoint.d.ts +12 -1
  85. package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
  86. package/dist/src/orgrt/checkpoint.js +15 -6
  87. package/dist/src/orgrt/checkpoint.js.map +1 -1
  88. package/dist/src/orgrt/completion-gate.d.ts +74 -0
  89. package/dist/src/orgrt/completion-gate.d.ts.map +1 -1
  90. package/dist/src/orgrt/completion-gate.js +45 -0
  91. package/dist/src/orgrt/completion-gate.js.map +1 -1
  92. package/dist/src/orgrt/cost-tier.d.ts +144 -0
  93. package/dist/src/orgrt/cost-tier.d.ts.map +1 -0
  94. package/dist/src/orgrt/cost-tier.js +183 -0
  95. package/dist/src/orgrt/cost-tier.js.map +1 -0
  96. package/dist/src/orgrt/cross-org.d.ts.map +1 -1
  97. package/dist/src/orgrt/cross-org.js +14 -0
  98. package/dist/src/orgrt/cross-org.js.map +1 -1
  99. package/dist/src/orgrt/daemon.d.ts +12 -1
  100. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  101. package/dist/src/orgrt/daemon.js +216 -49
  102. package/dist/src/orgrt/daemon.js.map +1 -1
  103. package/dist/src/orgrt/decisions.d.ts +14 -2
  104. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  105. package/dist/src/orgrt/decisions.js +216 -10
  106. package/dist/src/orgrt/decisions.js.map +1 -1
  107. package/dist/src/orgrt/file-roots.d.ts +7 -0
  108. package/dist/src/orgrt/file-roots.d.ts.map +1 -1
  109. package/dist/src/orgrt/file-roots.js +38 -1
  110. package/dist/src/orgrt/file-roots.js.map +1 -1
  111. package/dist/src/orgrt/forwarder.d.ts.map +1 -1
  112. package/dist/src/orgrt/forwarder.js +16 -2
  113. package/dist/src/orgrt/forwarder.js.map +1 -1
  114. package/dist/src/orgrt/idle-deadline.d.ts +74 -1
  115. package/dist/src/orgrt/idle-deadline.d.ts.map +1 -1
  116. package/dist/src/orgrt/idle-deadline.js +52 -2
  117. package/dist/src/orgrt/idle-deadline.js.map +1 -1
  118. package/dist/src/orgrt/loadouts.d.ts +38 -0
  119. package/dist/src/orgrt/loadouts.d.ts.map +1 -0
  120. package/dist/src/orgrt/loadouts.js +129 -0
  121. package/dist/src/orgrt/loadouts.js.map +1 -0
  122. package/dist/src/orgrt/mailbox.d.ts +17 -1
  123. package/dist/src/orgrt/mailbox.d.ts.map +1 -1
  124. package/dist/src/orgrt/mailbox.js +50 -3
  125. package/dist/src/orgrt/mailbox.js.map +1 -1
  126. package/dist/src/orgrt/policy.d.ts +42 -2
  127. package/dist/src/orgrt/policy.d.ts.map +1 -1
  128. package/dist/src/orgrt/policy.js +53 -8
  129. package/dist/src/orgrt/policy.js.map +1 -1
  130. package/dist/src/orgrt/prompt-vars.d.ts +11 -0
  131. package/dist/src/orgrt/prompt-vars.d.ts.map +1 -0
  132. package/dist/src/orgrt/prompt-vars.js +49 -0
  133. package/dist/src/orgrt/prompt-vars.js.map +1 -0
  134. package/dist/src/orgrt/questions.d.ts +22 -1
  135. package/dist/src/orgrt/questions.d.ts.map +1 -1
  136. package/dist/src/orgrt/questions.js +24 -3
  137. package/dist/src/orgrt/questions.js.map +1 -1
  138. package/dist/src/orgrt/review-packet.d.ts +29 -0
  139. package/dist/src/orgrt/review-packet.d.ts.map +1 -0
  140. package/dist/src/orgrt/review-packet.js +67 -0
  141. package/dist/src/orgrt/review-packet.js.map +1 -0
  142. package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
  143. package/dist/src/orgrt/role-sandbox.js +16 -3
  144. package/dist/src/orgrt/role-sandbox.js.map +1 -1
  145. package/dist/src/orgrt/session-ledger.d.ts +61 -0
  146. package/dist/src/orgrt/session-ledger.d.ts.map +1 -0
  147. package/dist/src/orgrt/session-ledger.js +113 -0
  148. package/dist/src/orgrt/session-ledger.js.map +1 -0
  149. package/dist/src/orgrt/session.d.ts +45 -5
  150. package/dist/src/orgrt/session.d.ts.map +1 -1
  151. package/dist/src/orgrt/session.js +384 -27
  152. package/dist/src/orgrt/session.js.map +1 -1
  153. package/dist/src/orgrt/task-dag.d.ts +34 -1
  154. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  155. package/dist/src/orgrt/task-dag.js +58 -7
  156. package/dist/src/orgrt/task-dag.js.map +1 -1
  157. package/dist/src/orgrt/tool-spill.d.ts +94 -0
  158. package/dist/src/orgrt/tool-spill.d.ts.map +1 -0
  159. package/dist/src/orgrt/tool-spill.js +180 -0
  160. package/dist/src/orgrt/tool-spill.js.map +1 -0
  161. package/dist/src/orgrt/types.d.ts +138 -0
  162. package/dist/src/orgrt/types.d.ts.map +1 -1
  163. package/dist/src/orgrt/types.js +148 -0
  164. package/dist/src/orgrt/types.js.map +1 -1
  165. package/dist/src/platform-adapters/renderers/mcp.d.ts +20 -2
  166. package/dist/src/platform-adapters/renderers/mcp.d.ts.map +1 -1
  167. package/dist/src/platform-adapters/renderers/mcp.js +25 -5
  168. package/dist/src/platform-adapters/renderers/mcp.js.map +1 -1
  169. package/dist/src/platform-adapters/renderers/skills.d.ts +0 -6
  170. package/dist/src/platform-adapters/renderers/skills.d.ts.map +1 -1
  171. package/dist/src/platform-adapters/renderers/skills.js +12 -22
  172. package/dist/src/platform-adapters/renderers/skills.js.map +1 -1
  173. package/dist/src/protocol-capabilities.d.ts +2 -1
  174. package/dist/src/protocol-capabilities.d.ts.map +1 -1
  175. package/dist/src/protocol-capabilities.js +2 -1
  176. package/dist/src/protocol-capabilities.js.map +1 -1
  177. package/dist/src/ui/dashboard.html +457 -164
  178. package/dist/src/ui/org-hil.mjs +276 -0
  179. package/dist/src/ui/org-runtime.mjs +350 -0
  180. package/dist/src/ui/orgs.html +22 -4
  181. package/dist/src/ui/routes-monoes.mjs +28 -3
  182. package/dist/src/ui/routes-org.mjs +290 -541
  183. package/dist/src/ui/server.mjs +185 -19
  184. package/dist/tsconfig.tsbuildinfo +1 -1
  185. package/package.json +7 -6
@@ -55,4 +55,78 @@ export interface CompletionFacts {
55
55
  /** Decide whether an `org_complete` call is honest, given already-gathered
56
56
  * facts. Returns a refusal message, or `null` to allow. */
57
57
  export declare function checkCompletion(f: CompletionFacts): string | null;
58
+ /**
59
+ * The gate above asks "is this claim about the RUN honest?".
60
+ * `checkTaskEvidence` asks the same question one level down, about a single
61
+ * item: "may this role close this task, and is there anything but its own
62
+ * opinion saying it is done?".
63
+ *
64
+ * Why: one measured run produced 223 gate verdicts for 15 finished items —
65
+ * ~15 opinions per item — and still shipped five controls that could not
66
+ * fail. Three times the verifier FAILED a sha the reviewer had already
67
+ * APPROVED, and the verifier was right every time. Every one of those
68
+ * verdicts was an LLM judgment with nothing checking it.
69
+ *
70
+ * Ported from Gas Town's `gt done` (internal/cmd/done.go:498-526), which
71
+ * refuses to retire review work unless the item carries a fresh evidence
72
+ * comment. Its five tests map onto this runtime as:
73
+ * 1. posted after work started — STRUCTURAL here, not a check: evidence is
74
+ * an argument OF the org_task_done call, so it cannot predate the call.
75
+ * Gas Town needs `attached_at` because its evidence is a comment that
76
+ * persists on the item independently of the close.
77
+ * 2. authored by the assignee — `caller` is the RUNTIME's view of which
78
+ * role invoked the tool (session.ts binds it per role), compared here
79
+ * against the task's assignee. Deliberately not a self-declared author
80
+ * field, which an agent could simply write.
81
+ * 3. machine-parseable prefix — replaced by something stronger: evidence is
82
+ * a typed {command, exitCode, output} record. There is no prose to
83
+ * regex, and "an acceptance criterion is a command with an exit code"
84
+ * (D5) becomes expressible in the type itself.
85
+ * 4. not machine-generated — n/a, see 3.
86
+ * 5. head_sha equal to the current HEAD — ported as-is, and the
87
+ * load-bearing one: evidence gathered before the last commit is STALE.
88
+ * The work moved; the proof did not.
89
+ *
90
+ * What this does NOT do, stated plainly rather than implied: the runtime does
91
+ * not re-execute the command. A role can still report exitCode 0 for a
92
+ * command it never ran. What the gate buys is that the proof must name a
93
+ * runnable command, must be attributable, and must be pinned to the tree
94
+ * state being closed — so it cannot be recycled across commits, which is the
95
+ * failure actually observed. Re-executing the acceptance commands from the
96
+ * daemon is the strictly stronger version and the obvious next step; it needs
97
+ * a decision about where those commands run (role sandbox vs daemon) that is
98
+ * out of scope here.
99
+ *
100
+ * Opt-in: `run_config.completion_evidence` (default false). Turning it on
101
+ * refuses completions that previously succeeded — that IS the point — so it
102
+ * must never be on by default, or every existing org breaks on upgrade.
103
+ */
104
+ /** One acceptance criterion: a command, the exit code it actually returned,
105
+ * and what it printed. */
106
+ export interface EvidenceCheck {
107
+ command: string;
108
+ exitCode: number;
109
+ output?: string;
110
+ }
111
+ export interface TaskEvidence {
112
+ /** The commit sha the checks were run against. */
113
+ headSha: string;
114
+ checks: EvidenceCheck[];
115
+ }
116
+ export interface TaskEvidenceFacts {
117
+ /** `run_config.completion_evidence`. False (the default) allows everything. */
118
+ required: boolean;
119
+ evidence?: TaskEvidence;
120
+ /** The workspace's real current commit sha, resolved by the caller.
121
+ * Undefined when the workspace is not a git repository. */
122
+ headSha?: string;
123
+ /** Role id the runtime saw calling org_task_done. */
124
+ caller: string;
125
+ /** The task's recorded assignee. */
126
+ assignee: string;
127
+ }
128
+ /** Decide whether a role may close a task, given already-gathered facts.
129
+ * Returns a refusal message, or `null` to allow. Pure: the caller resolves
130
+ * the head sha and the assignee. */
131
+ export declare function checkTaskEvidence(f: TaskEvidenceFacts): string | null;
58
132
  //# sourceMappingURL=completion-gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"completion-gate.d.ts","sourceRoot":"","sources":["../../../src/orgrt/completion-gate.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAClE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;mFAE+E;IAC/E,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;kEAE8D;IAC9D,cAAc,EAAE,OAAO,CAAC;IACxB;;;;sBAIkB;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAiDD;4DAC4D;AAC5D,wBAAgB,eAAe,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CASjE"}
1
+ {"version":3,"file":"completion-gate.d.ts","sourceRoot":"","sources":["../../../src/orgrt/completion-gate.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAClE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;mFAE+E;IAC/E,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;kEAE8D;IAC9D,cAAc,EAAE,OAAO,CAAC;IACxB;;;;sBAIkB;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAiDD;4DAC4D;AAC5D,wBAAgB,eAAe,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CASjE;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH;2BAC2B;AAC3B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;gEAC4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD;;qCAEqC;AACrC,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAoCrE"}
@@ -83,4 +83,49 @@ export function checkCompletion(f) {
83
83
  }
84
84
  return null;
85
85
  }
86
+ /** Shortest sha prefix accepted — the git default short length. Below that a
87
+ * prefix identifies nothing. */
88
+ const MIN_SHA_LEN = 7;
89
+ const EVIDENCE_SHAPE = 'Attach evidence: { headSha: "<the current commit sha>", checks: [{ command, exitCode, output }] } — one entry per acceptance criterion, each a command you actually ran, with its real exit code and its output.';
90
+ /** Decide whether a role may close a task, given already-gathered facts.
91
+ * Returns a refusal message, or `null` to allow. Pure: the caller resolves
92
+ * the head sha and the assignee. */
93
+ export function checkTaskEvidence(f) {
94
+ if (!f.required)
95
+ return null;
96
+ if (f.caller !== f.assignee) {
97
+ return `org_task_done refused: this task is assigned to "${f.assignee}", and evidence only counts from the assignee. Ask "${f.assignee}" to close it, or reassign the task first.`;
98
+ }
99
+ const ev = f.evidence;
100
+ if (!ev) {
101
+ return `org_task_done refused (run_config.completion_evidence): closing a task needs verifiable evidence, not a summary. ${EVIDENCE_SHAPE}`;
102
+ }
103
+ if (ev.checks.length === 0) {
104
+ return `org_task_done refused: the evidence names no acceptance command. An acceptance criterion is a command with an exit code — if you cannot write one, the criterion is too vague to close on. ${EVIDENCE_SHAPE}`;
105
+ }
106
+ for (const c of ev.checks) {
107
+ if (!c.command.trim()) {
108
+ return `org_task_done refused: an evidence entry has an empty command. Every check must name the command that was actually run. ${EVIDENCE_SHAPE}`;
109
+ }
110
+ }
111
+ const failed = ev.checks.filter((c) => c.exitCode !== 0);
112
+ if (failed.length > 0) {
113
+ const detail = failed
114
+ .map((c) => ` $ ${c.command}\n exit ${c.exitCode}${c.output ? `\n ${c.output}` : ''}`)
115
+ .join('\n');
116
+ return `org_task_done refused: ${failed.length} acceptance command(s) did not exit 0 — the task is not done.\n${detail}\nFix the failure, re-run the checks, and close it again; the task goes back in your queue.`;
117
+ }
118
+ if (!f.headSha) {
119
+ return 'org_task_done refused: evidence must be pinned to a commit, but this workspace has no resolvable git HEAD. Either run this org in a git workspace, or turn run_config.completion_evidence off.';
120
+ }
121
+ const claimed = ev.headSha.trim().toLowerCase();
122
+ const actual = f.headSha.trim().toLowerCase();
123
+ if (claimed.length < MIN_SHA_LEN) {
124
+ return `org_task_done refused: headSha "${ev.headSha}" is too short to identify a commit (at least ${MIN_SHA_LEN} characters). The current head is ${actual}.`;
125
+ }
126
+ if (!actual.startsWith(claimed)) {
127
+ return `org_task_done refused: the evidence is STALE. It is pinned to ${claimed}, but the current head is ${actual} — the tree moved after those checks ran, so they say nothing about the code being closed. Re-run the acceptance commands against the current head and attach the new output.`;
128
+ }
129
+ return null;
130
+ }
86
131
  //# sourceMappingURL=completion-gate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"completion-gate.js","sourceRoot":"","sources":["../../../src/orgrt/completion-gate.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AA6BH;yEACyE;AACzE,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B;6CAC6C;AAC7C,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B;4BAC4B;AAC5B,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAE3C,MAAM,UAAU,GACd,ybAAyb,CAAC;AAE5b,SAAS,YAAY,CAAC,CAAkB;IACtC,IAAI,CAAC,CAAC,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC;IAClC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;QAClB,KAAK,UAAU,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;gBAC3E,OAAO,iGAAiG,cAAc,wOAAwO,CAAC;YACjW,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,CAAC,iBAAiB,GAAG,gBAAgB,EAAE,CAAC;gBAC3C,OAAO,sFAAsF,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,GAAG,GAAG,CAAC,wJAAwJ,CAAC;YAC7R,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,wOAAwO,CAAC;YAClP,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,uOAAuO,CAAC;YACjP,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,GACpB,0PAA0P,CAAC;AAE7P;4DAC4D;AAC5D,MAAM,UAAU,eAAe,CAAC,CAAkB;IAChD,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;QACxF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"completion-gate.js","sourceRoot":"","sources":["../../../src/orgrt/completion-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * ADR-O001 D8 — cost tiers: a named cost level that sets BOTH the model AND
3
+ * the reasoning/thinking effort for a role, on whatever provider that role
4
+ * runs on.
5
+ *
6
+ * Measured on one real org run, holding volume constant: all-Opus $1,744,
7
+ * as-run blended $1,050, all-Sonnet $698, all-Haiku $349. Tiering is roughly
8
+ * a 3x win and is independent of every other D-decision.
9
+ *
10
+ * ──────────────────────────────────────────────────────────────────────────
11
+ * DO NOT TIER A DELIBERATIVE ROLE INTO A WEAK VOICE.
12
+ *
13
+ * ADR-O001, "What this does NOT apply to — deliberation and debate":
14
+ *
15
+ * "do not tier a debate participant into a weak voice. Tier by
16
+ * *difficulty of the judgement*, not by role label. A cheap model in a
17
+ * debate produces cheap arguments and the synthesiser cannot tell."
18
+ *
19
+ * Tier by how hard the judgement is, not by what the role is called. A role
20
+ * whose value is the quality of its disagreement — a design reviewer, a
21
+ * red-teamer, a debate participant, a synthesiser reading every position —
22
+ * belongs at `"exempt"` (see EXEMPT_TIER), which opts it out of tiering
23
+ * entirely and leaves its model exactly as it was. Control its cost with a
24
+ * budget (D1), not with a cheaper model.
25
+ * ──────────────────────────────────────────────────────────────────────────
26
+ *
27
+ * Three properties this deliberately has:
28
+ *
29
+ * - **Defaulted off.** An org that declares no `cost_tiers` resolves to
30
+ * `undefined` here and behaves byte-identically to before. Asserted by
31
+ * org-cost-tier.test.ts, not merely promised by this comment.
32
+ *
33
+ * - **Provider-agnostic.** A tier is a table keyed by *provider key* — a
34
+ * Vercel vendor slug (`glm`, `openai`, …) when the role has one, else the
35
+ * role's runtime id (`codex`, `kimicode`, `claude`, …). The built-in
36
+ * catalog covers Claude only (the default and the only provider whose
37
+ * model ids and effort mechanism this repo can verify); every other
38
+ * provider — including one this code has never heard of — is declared in
39
+ * the org config with no code change.
40
+ *
41
+ * - **Never a silent downgrade.** If a tier has no entry for a role's
42
+ * provider, resolution THROWS (and `validateCostTiers` reports it at org
43
+ * start, before a token is spent) rather than quietly picking something.
44
+ *
45
+ * Effort is abstract here (`off | low | medium | high | xhigh | max`, the
46
+ * Claude Agent SDK's own vocabulary plus an explicit `off`). Each provider
47
+ * expresses it its own way:
48
+ * - Claude: natively — session.ts hands it to the runner, which sets the
49
+ * SDK's `effort` option (or `thinking: {type:'disabled'}` for `off`).
50
+ * - Any other provider: whatever env vars the org declares under
51
+ * `cost_tiers.providers.<key>.effort_env.<level>`, merged into the
52
+ * session env. Providers that encode effort in the model id instead
53
+ * (e.g. `gemini-3.6-flash-high`) need nothing extra — name the model
54
+ * you want per tier.
55
+ * - A provider with no mechanism at all simply ignores the level.
56
+ */
57
+ import type { OrgDef, OrgRole } from './types.js';
58
+ /** Abstract reasoning-effort level. Mirrors the Claude Agent SDK's
59
+ * `EffortLevel` ('low' | 'medium' | 'high' | 'xhigh' | 'max') plus an
60
+ * explicit 'off' meaning "no extended thinking at all". */
61
+ export declare const ORG_EFFORT_LEVELS: readonly ['off', 'low', 'medium', 'high', 'xhigh', 'max'];
62
+ export type OrgEffortLevel = (typeof ORG_EFFORT_LEVELS)[number];
63
+ /** Reserved tier name: this role is not tiered at all. See the header. */
64
+ export declare const EXEMPT_TIER = "exempt";
65
+ /** What one tier resolves to for one provider. */
66
+ export interface CostTierEntry {
67
+ model: string;
68
+ effort?: OrgEffortLevel;
69
+ }
70
+ /** A tier: provider key → entry. */
71
+ export type CostTierDef = Record<string, CostTierEntry>;
72
+ /** How one provider expresses an effort level, when it can. */
73
+ export interface CostTierProviderDef {
74
+ /** Env vars to set for the session, per effort level. */
75
+ effort_env?: Partial<Record<OrgEffortLevel, Record<string, string>>>;
76
+ }
77
+ /** The org's `cost_tiers` block. */
78
+ export interface CostTiersConfig {
79
+ /** Tier applied to every role that has no entry in `roles`. */
80
+ default?: string;
81
+ /** Per-role assignment. A bare string is a tier name (or `"exempt"`);
82
+ * the object form additionally overrides the tier's effort, which is how
83
+ * "patrol roles drop effort since they do simpler, more repetitive work"
84
+ * is expressed without minting a whole extra tier. */
85
+ roles?: Record<string, string | {
86
+ tier: string;
87
+ effort?: OrgEffortLevel;
88
+ }>;
89
+ /** User catalog. Merged OVER the built-in catalog per tier, per provider —
90
+ * so adding `{economy: {codex: …}}` extends built-in `economy` rather than
91
+ * replacing its `claude` entry. */
92
+ tiers?: Record<string, CostTierDef>;
93
+ /** Per-provider effort expression. */
94
+ providers?: Record<string, CostTierProviderDef>;
95
+ }
96
+ /** Built-in catalog. Claude only, on purpose: these are the model ids and the
97
+ * effort mechanism this repo can actually verify. Tiering a role on any other
98
+ * provider means naming that provider's models in `cost_tiers.tiers` — which
99
+ * is the honest alternative to inventing model ids and downgrading a role
100
+ * onto a string nobody checked. */
101
+ export declare const BUILTIN_COST_TIERS: Record<string, CostTierDef>;
102
+ /** Thrown when a tier cannot resolve a model for a role's provider, or names
103
+ * a tier that does not exist. Never swallowed into a default — see header. */
104
+ export declare class CostTierError extends Error {
105
+ }
106
+ /** The provider key a role tiers under: its Vercel vendor slug when it has
107
+ * one (that is what actually picks the model), else its runtime id, else the
108
+ * org's runtime, else 'claude'. Mirrors resolveModel()'s own vendor-then-
109
+ * runtime precedence in session.ts. */
110
+ export declare function costTierProviderKey(role: Pick<OrgRole, 'runtime' | 'provider'>, orgRuntime?: string, vendor?: string): string;
111
+ /** What a role's tier resolved to. */
112
+ export interface ResolvedCostTier {
113
+ tier: string;
114
+ provider: string;
115
+ model: string;
116
+ effort?: OrgEffortLevel;
117
+ /** Env vars expressing `effort` for this provider; `{}` when the provider
118
+ * has no env mechanism (Claude, which is handled natively, or a provider
119
+ * with none at all). */
120
+ env: Record<string, string>;
121
+ }
122
+ /**
123
+ * Resolve the cost tier for one role. Returns `undefined` when the org
124
+ * declares no tiers, when the role is assigned none, or when it is
125
+ * `"exempt"` — all of which mean "leave this role exactly as it was".
126
+ *
127
+ * Throws CostTierError when a tier IS assigned but cannot be honoured, so a
128
+ * misconfigured tier is a loud failure rather than a silent downgrade.
129
+ */
130
+ export declare function resolveRoleCostTier(args: {
131
+ role: OrgRole;
132
+ def?: Pick<OrgDef, 'runtime' | 'cost_tiers'> & Record<string, unknown>;
133
+ /** Vendor override, when the caller already resolved a named provider's
134
+ * vendor (session.ts does). */
135
+ vendor?: string;
136
+ }): ResolvedCostTier | undefined;
137
+ /**
138
+ * Every cost-tier problem in an org definition, as human-readable lines.
139
+ * Empty for an org that declares no tiers (the upgrade-safe case). Called by
140
+ * the daemon before it spawns anything — a tier that cannot resolve must fail
141
+ * the run at start, not ten minutes and a wrong model later.
142
+ */
143
+ export declare function validateCostTiers(def: OrgDef): string[];
144
+ //# sourceMappingURL=cost-tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tier.d.ts","sourceRoot":"","sources":["../../../src/orgrt/cost-tier.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAElD;;4DAE4D;AAC5D,eAAO,MAAM,iBAAiB,YAAI,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAU,CAAC;AAC3F,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,0EAA0E;AAC1E,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,oCAAoC;AACpC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAExD,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CACtE;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;2DAGuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IAC3E;;wCAEoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACjD;AAED;;;;oCAIoC;AACpC,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAa1D,CAAC;AAEF;+EAC+E;AAC/E,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C;;;wCAGwC;AACxC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,UAAU,CAAC,EAC3C,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAER;AAED,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB;;6BAEyB;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAoBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvE;oCACgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,gBAAgB,GAAG,SAAS,CAiC/B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAiCvD"}
@@ -0,0 +1,183 @@
1
+ // packages/@monomind/cli/src/orgrt/cost-tier.ts
2
+ /**
3
+ * ADR-O001 D8 — cost tiers: a named cost level that sets BOTH the model AND
4
+ * the reasoning/thinking effort for a role, on whatever provider that role
5
+ * runs on.
6
+ *
7
+ * Measured on one real org run, holding volume constant: all-Opus $1,744,
8
+ * as-run blended $1,050, all-Sonnet $698, all-Haiku $349. Tiering is roughly
9
+ * a 3x win and is independent of every other D-decision.
10
+ *
11
+ * ──────────────────────────────────────────────────────────────────────────
12
+ * DO NOT TIER A DELIBERATIVE ROLE INTO A WEAK VOICE.
13
+ *
14
+ * ADR-O001, "What this does NOT apply to — deliberation and debate":
15
+ *
16
+ * "do not tier a debate participant into a weak voice. Tier by
17
+ * *difficulty of the judgement*, not by role label. A cheap model in a
18
+ * debate produces cheap arguments and the synthesiser cannot tell."
19
+ *
20
+ * Tier by how hard the judgement is, not by what the role is called. A role
21
+ * whose value is the quality of its disagreement — a design reviewer, a
22
+ * red-teamer, a debate participant, a synthesiser reading every position —
23
+ * belongs at `"exempt"` (see EXEMPT_TIER), which opts it out of tiering
24
+ * entirely and leaves its model exactly as it was. Control its cost with a
25
+ * budget (D1), not with a cheaper model.
26
+ * ──────────────────────────────────────────────────────────────────────────
27
+ *
28
+ * Three properties this deliberately has:
29
+ *
30
+ * - **Defaulted off.** An org that declares no `cost_tiers` resolves to
31
+ * `undefined` here and behaves byte-identically to before. Asserted by
32
+ * org-cost-tier.test.ts, not merely promised by this comment.
33
+ *
34
+ * - **Provider-agnostic.** A tier is a table keyed by *provider key* — a
35
+ * Vercel vendor slug (`glm`, `openai`, …) when the role has one, else the
36
+ * role's runtime id (`codex`, `kimicode`, `claude`, …). The built-in
37
+ * catalog covers Claude only (the default and the only provider whose
38
+ * model ids and effort mechanism this repo can verify); every other
39
+ * provider — including one this code has never heard of — is declared in
40
+ * the org config with no code change.
41
+ *
42
+ * - **Never a silent downgrade.** If a tier has no entry for a role's
43
+ * provider, resolution THROWS (and `validateCostTiers` reports it at org
44
+ * start, before a token is spent) rather than quietly picking something.
45
+ *
46
+ * Effort is abstract here (`off | low | medium | high | xhigh | max`, the
47
+ * Claude Agent SDK's own vocabulary plus an explicit `off`). Each provider
48
+ * expresses it its own way:
49
+ * - Claude: natively — session.ts hands it to the runner, which sets the
50
+ * SDK's `effort` option (or `thinking: {type:'disabled'}` for `off`).
51
+ * - Any other provider: whatever env vars the org declares under
52
+ * `cost_tiers.providers.<key>.effort_env.<level>`, merged into the
53
+ * session env. Providers that encode effort in the model id instead
54
+ * (e.g. `gemini-3.6-flash-high`) need nothing extra — name the model
55
+ * you want per tier.
56
+ * - A provider with no mechanism at all simply ignores the level.
57
+ */
58
+ /** Abstract reasoning-effort level. Mirrors the Claude Agent SDK's
59
+ * `EffortLevel` ('low' | 'medium' | 'high' | 'xhigh' | 'max') plus an
60
+ * explicit 'off' meaning "no extended thinking at all". */
61
+ export const ORG_EFFORT_LEVELS = ['off', 'low', 'medium', 'high', 'xhigh', 'max'];
62
+ /** Reserved tier name: this role is not tiered at all. See the header. */
63
+ export const EXEMPT_TIER = 'exempt';
64
+ /** Built-in catalog. Claude only, on purpose: these are the model ids and the
65
+ * effort mechanism this repo can actually verify. Tiering a role on any other
66
+ * provider means naming that provider's models in `cost_tiers.tiers` — which
67
+ * is the honest alternative to inventing model ids and downgrading a role
68
+ * onto a string nobody checked. */
69
+ export const BUILTIN_COST_TIERS = {
70
+ standard: {
71
+ claude: { model: 'claude-opus-5', effort: 'high' },
72
+ anthropic: { model: 'claude-opus-5', effort: 'high' },
73
+ },
74
+ economy: {
75
+ claude: { model: 'claude-sonnet-5', effort: 'medium' },
76
+ anthropic: { model: 'claude-sonnet-5', effort: 'medium' },
77
+ },
78
+ budget: {
79
+ claude: { model: 'claude-haiku-4-5', effort: 'low' },
80
+ anthropic: { model: 'claude-haiku-4-5', effort: 'low' },
81
+ },
82
+ };
83
+ /** Thrown when a tier cannot resolve a model for a role's provider, or names
84
+ * a tier that does not exist. Never swallowed into a default — see header. */
85
+ export class CostTierError extends Error {
86
+ }
87
+ /** The provider key a role tiers under: its Vercel vendor slug when it has
88
+ * one (that is what actually picks the model), else its runtime id, else the
89
+ * org's runtime, else 'claude'. Mirrors resolveModel()'s own vendor-then-
90
+ * runtime precedence in session.ts. */
91
+ export function costTierProviderKey(role, orgRuntime, vendor) {
92
+ return vendor ?? role.provider?.vendor ?? role.runtime ?? orgRuntime ?? 'claude';
93
+ }
94
+ function catalogFor(config, tier) {
95
+ const builtin = BUILTIN_COST_TIERS[tier];
96
+ const user = config.tiers?.[tier];
97
+ if (!builtin && !user)
98
+ return undefined;
99
+ return { ...builtin, ...user };
100
+ }
101
+ /** The tier name assigned to a role, or undefined when it is untiered. */
102
+ function assignmentFor(config, roleId) {
103
+ const entry = config.roles?.[roleId];
104
+ if (typeof entry === 'string')
105
+ return { tier: entry };
106
+ if (entry)
107
+ return entry;
108
+ return config.default ? { tier: config.default } : undefined;
109
+ }
110
+ /**
111
+ * Resolve the cost tier for one role. Returns `undefined` when the org
112
+ * declares no tiers, when the role is assigned none, or when it is
113
+ * `"exempt"` — all of which mean "leave this role exactly as it was".
114
+ *
115
+ * Throws CostTierError when a tier IS assigned but cannot be honoured, so a
116
+ * misconfigured tier is a loud failure rather than a silent downgrade.
117
+ */
118
+ export function resolveRoleCostTier(args) {
119
+ const config = args.def?.cost_tiers;
120
+ if (!config)
121
+ return undefined;
122
+ const assignment = assignmentFor(config, args.role.id);
123
+ if (!assignment || assignment.tier === EXEMPT_TIER)
124
+ return undefined;
125
+ const tier = catalogFor(config, assignment.tier);
126
+ if (!tier) {
127
+ throw new CostTierError(`cost tier "${assignment.tier}" is not defined (built-in tiers: ${Object.keys(BUILTIN_COST_TIERS).join(', ')}; add it under cost_tiers.tiers, or use "${EXEMPT_TIER}" to opt this role out)`);
128
+ }
129
+ const provider = costTierProviderKey(args.role, args.def?.runtime, args.vendor);
130
+ const entry = tier[provider];
131
+ if (!entry) {
132
+ throw new CostTierError(`cost tier "${assignment.tier}" has no model for provider "${provider}" ` +
133
+ `(define cost_tiers.tiers.${assignment.tier}.${provider} = { "model": "…", "effort": "…" }, ` +
134
+ `or set this role's tier to "${EXEMPT_TIER}") — refusing to guess a cheaper model`);
135
+ }
136
+ const effort = assignment.effort ?? entry.effort;
137
+ const env = (effort && config.providers?.[provider]?.effort_env?.[effort]) ?? {};
138
+ return { tier: assignment.tier, provider, model: entry.model, effort, env };
139
+ }
140
+ /**
141
+ * Every cost-tier problem in an org definition, as human-readable lines.
142
+ * Empty for an org that declares no tiers (the upgrade-safe case). Called by
143
+ * the daemon before it spawns anything — a tier that cannot resolve must fail
144
+ * the run at start, not ten minutes and a wrong model later.
145
+ */
146
+ export function validateCostTiers(def) {
147
+ const config = def.cost_tiers;
148
+ if (!config)
149
+ return [];
150
+ const errors = [];
151
+ // A `default` or per-role tier naming a tier nobody defined is an error even
152
+ // if no role happens to reach it — it is always a typo.
153
+ const named = new Set();
154
+ if (config.default)
155
+ named.add(config.default);
156
+ for (const entry of Object.values(config.roles ?? {})) {
157
+ named.add(typeof entry === 'string' ? entry : entry.tier);
158
+ }
159
+ for (const tier of named) {
160
+ if (tier === EXEMPT_TIER)
161
+ continue;
162
+ if (!catalogFor(config, tier)) {
163
+ errors.push(`cost_tiers: tier "${tier}" is not defined (built-in: ${Object.keys(BUILTIN_COST_TIERS).join(', ')})`);
164
+ }
165
+ }
166
+ for (const role of def.roles ?? []) {
167
+ if (role.kind === 'endpoint')
168
+ continue; // endpoint roles run no model session
169
+ try {
170
+ resolveRoleCostTier({ role, def });
171
+ }
172
+ catch (err) {
173
+ if (!(err instanceof CostTierError))
174
+ throw err;
175
+ // The "tier not defined" case is already reported once above, by name.
176
+ if (err.message.startsWith('cost tier') && err.message.includes('is not defined'))
177
+ continue;
178
+ errors.push(`cost_tiers: role "${role.id}" — ${err.message}`);
179
+ }
180
+ }
181
+ return errors;
182
+ }
183
+ //# sourceMappingURL=cost-tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tier.js","sourceRoot":"","sources":["../../../src/orgrt/cost-tier.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cross-org.d.ts","sourceRoot":"","sources":["../../../src/orgrt/cross-org.ts"],"names":[],"mappings":"AAOA,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAS/E,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjF;AAsED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,GACT;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAMtE;AAED;;;mEAGmE;AACnE,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,UAAU,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,MAAM,CAWR;AAED;;;;;iEAKiE;AACjE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,OAAO,CAAC,CA0ClB;AAUD,mGAAmG;AACnG,wBAAsB,OAAO,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,OAAO,CAAC,MAAM,CAAC,CA8RjB;AAwMD,MAAM,WAAW,iBAAiB;IAChC;kEAC8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;oGAEoG;AACpG,wBAAsB,aAAa,CACjC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,EACvB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA6NvE"}
1
+ {"version":3,"file":"cross-org.d.ts","sourceRoot":"","sources":["../../../src/orgrt/cross-org.ts"],"names":[],"mappings":"AAOA,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAS/E,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjF;AAsED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,GACT;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAMtE;AAED;;;mEAGmE;AACnE,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,UAAU,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,MAAM,CAWR;AAED;;;;;iEAKiE;AACjE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,OAAO,CAAC,CA0ClB;AAUD,mGAAmG;AACnG,wBAAsB,OAAO,CAC3B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,OAAO,CAAC,MAAM,CAAC,CA4SjB;AAwMD,MAAM,WAAW,iBAAiB;IAChC;kEAC8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;oGAEoG;AACpG,wBAAsB,aAAa,CACjC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,EACvB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA6NvE"}
@@ -174,6 +174,20 @@ export async function deliver(daemon, fromOrg, fromRole, to, subject, body, opts
174
174
  const { cross, orgName: targetOrgName, role: targetRole, qualified: toQualified, } = resolveAddress(fromOrg, to);
175
175
  const targetOrg = daemon.orgs.get(targetOrgName);
176
176
  const src = daemon.orgs.get(fromOrg);
177
+ // ADR-O001 D6: an artifact-only reviewer takes runtime-built packets only.
178
+ // Another agent's mail is exactly the doer's framing D6 keeps out, so it is
179
+ // refused with the way to get a review instead. The human is not an agent.
180
+ const reviewerRole = targetOrg?.def.roles.find((r) => r.id === targetRole);
181
+ if (reviewerRole?.review_input === 'artifact-only' && (cross || fromRole !== 'human')) {
182
+ src?.bus.emit({
183
+ type: 'audit',
184
+ from: fromRole,
185
+ to: toQualified,
186
+ reason: 'review-mail-refused',
187
+ msg: `mail to artifact-only reviewer ${toQualified} refused: ${subject}`,
188
+ });
189
+ return `REFUSED: "${toQualified}" is an artifact-only reviewer and does not take messages from agents. Request a review with org_review(taskId, "${targetRole}") — it is built from the task, its evidence and the diff.`;
190
+ }
177
191
  // M2: an endpoint role has no mailbox — POST to its endpoint instead.
178
192
  const endpointRole = targetOrg ? findEndpointRole(targetOrg.def, targetRole) : undefined;
179
193
  if (targetOrg && endpointRole) {