@intentius/chant 0.124.0 → 0.124.2

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.
@@ -28,7 +28,11 @@
28
28
  * `clientInfo`. Computed provenance, from git, is unchanged.
29
29
  *
30
30
  * Nothing here listens on a port or authenticates anyone (ws-052): the server
31
- * speaks over stdio, and `by` is recorded as given, as `--by` is.
31
+ * speaks over stdio, and `by` is recorded as given, as `--by` is. A decision
32
+ * point's answer is the exception (#3817): `chant serve mcp` makes every call
33
+ * the model's (`lifecycle/gate-origin.ts`), so `points-answer` and
34
+ * `points-retract` count nobody `by` names toward a point's quorum, as
35
+ * `op-approve` records its approver as an agent.
32
36
  *
33
37
  * An agent session (#2548): a server started with `CHANT_AGENT` set writes in
34
38
  * that session, bound to its one member, and its writes are refused outside
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/workspace-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAe,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAKxE,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmBD,eAAO,MAAM,kBAAkB,EAAE,cAAc,EAkI9C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAAc,EA8G/C,CAAC;AAsCF,qHAAqH;AACrH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAyEhF;AA6CD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa,EAAE,CAyGpF"}
1
+ {"version":3,"file":"workspace-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/workspace-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EAAe,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAKxE,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmBD,eAAO,MAAM,kBAAkB,EAAE,cAAc,EAkI9C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAAc,EA8G/C,CAAC;AAsCF,qHAAqH;AACrH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAyEhF;AA6CD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,aAAa,EAAE,CAyGpF"}
@@ -1,21 +1,27 @@
1
1
  import type { GateLedgerPort } from "../op/gate.js";
2
2
  export declare const GATE_AUDIT_KINDS: readonly ["approval-requested", "approved", "override-requested", "override-recorded", "revoked", "applied", "override-spent"];
3
3
  export type GateAuditKind = (typeof GATE_AUDIT_KINDS)[number];
4
- /** How an approval was authenticated: an ssh seal, a forge review, or neither. */
4
+ /** How an approval was authorised: a forge review, an ssh seal, or neither. A review wins; a review that is also sealed has `sealed: true` beside it. */
5
5
  export type GateAuditSeal = "sealed" | "review" | "unsigned";
6
+ /** A commit that added or removed a ledger line: its date and its author's name and email. */
7
+ export interface GateLedgerCommit {
8
+ at: string;
9
+ by?: string;
10
+ email?: string;
11
+ }
6
12
  /**
7
13
  * One line of a ledger file. Give the `text` as it is on disk, or the parsed
8
- * `record` a {@link GateLedgerPort} returns. A line a commit removed carries
9
- * `removed`, with when and by whom (the commit's date and author).
14
+ * `record` a {@link GateLedgerPort} returns. `line` is its line number in the
15
+ * file, when known. A line read from history carries the commit that `added`
16
+ * it, or, if a commit removed it, `removed`, each with when and by whom.
10
17
  */
11
18
  export interface GateLedgerLine {
12
19
  text?: string;
13
20
  record?: unknown;
21
+ line?: number;
14
22
  commit?: string;
15
- removed?: {
16
- at: string;
17
- by?: string;
18
- };
23
+ added?: GateLedgerCommit;
24
+ removed?: GateLedgerCommit;
19
25
  }
20
26
  /** One op's ledger file. */
21
27
  export interface GateAuditLedger {
@@ -50,7 +56,13 @@ export interface GateAuditSource {
50
56
  /** The ledger file, or the apply's `ref` for an apply. */
51
57
  path: string;
52
58
  op?: string;
59
+ /** Ledger entries: the line's `line`, else its 1-based place in the ledger's `lines`. */
60
+ line?: number;
61
+ /** Ledger entries: the line's text exactly as passed in, when it was passed as text. */
62
+ text?: string;
53
63
  commit?: string;
64
+ /** The commit that added the line, or for a revocation removed it, when the line came from history. */
65
+ author?: GateLedgerCommit;
54
66
  change: "added" | "removed" | "apply";
55
67
  }
56
68
  export interface GateAuditEntry {
@@ -65,10 +77,14 @@ export interface GateAuditEntry {
65
77
  digest?: string;
66
78
  /** Who: the approver or overrider, whoever removed the line, or for an apply, whoever ran it. */
67
79
  by?: string;
68
- /** Resolutions and revocations: sealed, reviewed, or unsigned. */
80
+ /** Resolutions and revocations: reviewed, sealed, or unsigned. */
69
81
  seal?: GateAuditSeal;
82
+ /** The line holds an ssh seal, whatever `seal` says (a sealed review is `seal: "review"`). */
83
+ sealed?: true;
70
84
  /** The ssh signer, when sealed. */
71
85
  signer?: string;
86
+ /** Resolutions read from history: the author of the commit that added the line, who may not be `by`. */
87
+ committedBy?: string;
72
88
  /** Who carried the approval to chant (`chant approve --relayed-by`). */
73
89
  relayedBy?: string;
74
90
  /** A person or an agent, and the roles claimed. */
@@ -111,6 +127,12 @@ export interface GateAuditOptions {
111
127
  isOverride?: (op: string, gate: string) => boolean;
112
128
  /** Whether approvals of a gate need a seal or a review. Default none. */
113
129
  sealed?: (op: string, gate: string) => boolean;
130
+ /**
131
+ * The id to give an entry, from the entry with its default id. Default
132
+ * that id. A product with ids of its own keys by `entry.source` (its
133
+ * `path`, `line`, `text`). `under` refers to the ids this returns.
134
+ */
135
+ id?: (entry: GateAuditEntry) => string;
114
136
  }
115
137
  export interface GateAuditInput extends GateAuditOptions {
116
138
  ledgers: readonly GateAuditLedger[];
@@ -124,15 +146,17 @@ export declare function deriveGateAudit(input: GateAuditInput): {
124
146
  entries: GateAuditEntry[];
125
147
  gaps: GateAuditGap[];
126
148
  };
127
- /** The lines of one ledger file's text, all added. Blank lines are skipped. */
149
+ /** The lines of one ledger file's text, all added, each with its line number. Blank lines are skipped. */
128
150
  export declare function gateLedgerLines(content: string): GateLedgerLine[];
129
151
  /**
130
152
  * The lines each commit added to and removed from a ledger file, oldest first,
131
153
  * from `git log -p --unified=0 --no-renames` written with
132
- * `--format=%x1e%H%x1f%an%x1f%aI` over the file. The caller runs git; this
133
- * reads the text. A line removed and added again in one commit (a newline
134
- * fixed at the end of the file) is neither. A removed line is what
135
- * {@link deriveGateAudit} reports as a revocation.
154
+ * `--format=%x1e%H%x1f%an%x1f%aI` over the file (append `%x1f%ae` for the
155
+ * author's email). The caller runs git; this reads the text. Each line keeps
156
+ * its commit and that commit's date and author, as `added` or `removed`. A
157
+ * line removed and added again in one commit (a newline fixed at the end of
158
+ * the file) is neither. A removed line is what {@link deriveGateAudit}
159
+ * reports as a revocation.
136
160
  */
137
161
  export declare function gateLedgerLinesFromLog(log: string): GateLedgerLine[];
138
162
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"gate-audit.d.ts","sourceRoot":"","sources":["../../src/lifecycle/gate-audit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gate-audit.d.ts","sourceRoot":"","sources":["../../src/lifecycle/gate-audit.ts"],"names":[],"mappings":"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"}
@@ -48,13 +48,25 @@ export declare function isModelAuthored(origin: GateOrigin | undefined): boolean
48
48
  * the ledger exactly like a name a person gave. This is the honest value.
49
49
  */
50
50
  export declare const UNATTESTED_APPROVER = "unattested";
51
+ /**
52
+ * The environment variable a model-authored channel carries into child
53
+ * processes (chant#3817), as a steward's turn carries `CHANT_STEWARD`: a
54
+ * `chant workspace points answer` or `chant approve` a process on MCP or ACP
55
+ * starts is that channel's too. Only `mcp` and `acp` are read from it, so it
56
+ * can make a process model-authored and never make one a person's.
57
+ */
58
+ export declare const GATE_ORIGIN_ENV = "CHANT_GATE_ORIGIN";
51
59
  /**
52
60
  * Declare the channel this process serves. Called once at an entry point, not
53
61
  * per call: `chant mcp` sets `"mcp"` before it serves anything, `chant acp`
54
- * sets `"acp"`, and the CLI leaves the default.
62
+ * sets `"acp"`, and the CLI leaves the default. A model-authored channel is
63
+ * also exported as {@link GATE_ORIGIN_ENV}, so a child process knows it too.
55
64
  */
56
65
  export declare function setGateOrigin(origin: GateOrigin): void;
57
- /** The channel this process serves. `"cli"` unless an entry point said otherwise. */
66
+ /**
67
+ * The channel this process serves. `"cli"` unless an entry point said
68
+ * otherwise, or this process was started by one on MCP or ACP.
69
+ */
58
70
  export declare function currentGateOrigin(): GateOrigin;
59
71
  /** Restore the default. For tests, which must not leak a channel into each other. */
60
72
  export declare function resetGateOrigin(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"gate-origin.d.ts","sourceRoot":"","sources":["../../src/lifecycle/gate-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,gDAAgD;AAChD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAY/C,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAIhD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAEtD;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C;AAED,qFAAqF;AACrF,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,UAAU,GAAG,SAAS,EACrC,gBAAgB,EAAE,UAAU,GAC3B,MAAM,GAAG,SAAS,CAOpB"}
1
+ {"version":3,"file":"gate-origin.d.ts","sourceRoot":"","sources":["../../src/lifecycle/gate-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,gDAAgD;AAChD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAY/C,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAEvE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAIhD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGtD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,CAI9C;AAED,qFAAqF;AACrF,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,UAAU,GAAG,SAAS,EACrC,gBAAgB,EAAE,UAAU,GAC3B,MAAM,GAAG,SAAS,CAOpB"}
@@ -139,7 +139,9 @@ export interface OpWaveHookOutcome {
139
139
  /** The run, for a `perRun` hook. */
140
140
  target?: string;
141
141
  exit: number;
142
- outcome: "passed" | "failed" | "held";
142
+ outcome: "passed" | "failed" | "held" | "skipped";
143
+ /** Why the moment was skipped, for `skipped` (#3811). */
144
+ reason?: string;
143
145
  }
144
146
  /** One run as a hook sees it (#3804). */
145
147
  export interface OpWaveHookRun {
@@ -309,13 +311,16 @@ export declare function readOpWaveHooksFile(path?: string | undefined, cwd?: str
309
311
  * Each call adds its outcomes to the file's `result` (`CHANT_HOOKS_RESULT`),
310
312
  * which chant reads back after the apply exits: the outcomes join the wave's
311
313
  * result and decision record, and a hold makes the wave wait for, or find,
312
- * an approval of its digest. `exec` runs one hook; inject it to run a hook
314
+ * an approval of its digest. `skip: "<reason>"` runs nothing and records the
315
+ * moment as skipped with the reason (#3811), for an apply that changes nothing:
316
+ * chant counts the moment as handled. A skip without a reason throws. `exec` runs one hook; inject it to run a hook
313
317
  * in process or to keep its output.
314
318
  */
315
319
  export declare function runOpWaveApplyHooks(file: OpWaveHooksFile, moment: OpWaveHookMoment, options?: {
316
320
  cwd?: string;
317
321
  exec?: OpWaveExec;
318
322
  log?: (line: string) => void;
323
+ skip?: string;
319
324
  }): OpWaveApplyHooksRun;
320
325
  /**
321
326
  * The hooks of wave `wave` read at base, for an apply outside the waves
@@ -1 +1 @@
1
- {"version":3,"file":"op-waves-run.d.ts","sourceRoot":"","sources":["../../src/op/op-waves-run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"op-waves-run.d.ts","sourceRoot":"","sources":["../../src/op/op-waves-run.ts"],"names":[],"mappings":"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"}
@@ -46,11 +46,12 @@ import { type KindView } from "./records-write.js";
46
46
  import { type Asked, type Escalation, type ModelAsk, type Point } from "./points.js";
47
47
  import { type TrustPolicy } from "./trust/policy.js";
48
48
  import type { SourceVia } from "./source-block.js";
49
+ import { type GateOrigin } from "../lifecycle/gate-origin.js";
49
50
  /** The version of the write documents `points ask`, `points answer` and `points retract` print. */
50
51
  export declare const POINTS_WRITE_CONTRACT_VERSION = 1;
51
52
  export declare const POINTS_WRITE_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/points-write/v1/points-write.schema.json";
52
53
  /** Why `points ask`, `points answer` or `points retract` wrote nothing. Closed: a reader may switch on it. */
53
- export declare const POINTS_WRITE_ERROR_CODES: readonly ["kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "write-usage-invalid", "write-input-invalid", "points-undeclared", "points-invalid", "point-unknown", "point-inputs-invalid", "point-decider-failed", "answer-not-candidate", "quorum-not-met", "record-not-found", "record-closed", "record-id-taken", "answer-in-steward-turn", "principal-unidentified", "answer-not-answered", "answer-field-unsupported", "point-candidates-invalid", "write-lock-timeout", "write-lock-not-held", "record-unparseable", "record-schema-invalid", "record-id-duplicate", "record-supersedes-unknown", "record-supersedes-conflict", "record-remediates-unknown", "record-remediates-not-closed", "record-seal-mismatch", "session-seal-mismatch", "session-verdict-unknown-record"];
54
+ export declare const POINTS_WRITE_ERROR_CODES: readonly ["kind-unreadable", "kind-invalid", "schema-unreadable", "schema-id-mismatch", "schema-invalid", "location-missing", "write-usage-invalid", "write-input-invalid", "points-undeclared", "points-invalid", "point-unknown", "point-inputs-invalid", "point-decider-failed", "answer-not-candidate", "quorum-not-met", "record-not-found", "record-closed", "record-id-taken", "answer-in-steward-turn", "answer-never-over-mcp", "principal-unidentified", "answer-not-answered", "answer-field-unsupported", "point-candidates-invalid", "write-lock-timeout", "write-lock-not-held", "record-unparseable", "record-schema-invalid", "record-id-duplicate", "record-supersedes-unknown", "record-supersedes-conflict", "record-remediates-unknown", "record-remediates-not-closed", "record-seal-mismatch", "session-seal-mismatch", "session-verdict-unknown-record"];
54
55
  export type PointsWriteErrorCode = (typeof POINTS_WRITE_ERROR_CODES)[number];
55
56
  export declare class PointsWriteError extends Error {
56
57
  readonly code: PointsWriteErrorCode;
@@ -277,6 +278,13 @@ export interface AnswerPointOptions {
277
278
  kind?: string;
278
279
  on?: string;
279
280
  dryRun?: boolean;
281
+ /**
282
+ * The channel the answer came through (#3817). Defaults to this process's
283
+ * (`currentGateOrigin`). Over MCP or ACP nobody `by` names counts toward
284
+ * the quorum, and a question that constrains a `neverOverMcp` gate is
285
+ * refused outright.
286
+ */
287
+ origin?: GateOrigin;
280
288
  }
281
289
  /**
282
290
  * Whether an answer kind's schema copy takes the fields of #3351 (`note` on an
@@ -328,6 +336,8 @@ export interface RetractAnswerOptions {
328
336
  kind?: string;
329
337
  on?: string;
330
338
  dryRun?: boolean;
339
+ /** The channel the retraction came through, counted as for an answer (#3817). */
340
+ origin?: GateOrigin;
331
341
  }
332
342
  /**
333
343
  * People take an answer back: `points retract` (#3351, ws-084). The answer
@@ -1 +1 @@
1
- {"version":3,"file":"decide.d.ts","sourceRoot":"","sources":["../../src/workspace/decide.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decide.d.ts","sourceRoot":"","sources":["../../src/workspace/decide.ts"],"names":[],"mappings":"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"}
@@ -132,8 +132,9 @@ export declare const REASONS: {
132
132
  readonly "point-inputs-invalid": "The inputs given to an ask are not a JSON object of the point's declared inputs.";
133
133
  readonly "point-decider-failed": "A model decider that fails closed (unreachable: fail) could not answer, so the ask wrote nothing.";
134
134
  readonly "answer-not-candidate": "The people's answer is not one of the question's candidates.";
135
- readonly "quorum-not-met": "Too few of the people who answered count toward the point's quorum: distinct, not holding the agent role, not the steward that asked, and holding one of its roles when it names any.";
135
+ readonly "quorum-not-met": "Too few of the people who answered count toward the point's quorum: distinct, not holding the agent role, not the steward that asked, and holding one of its roles when it names any. Nobody named over MCP or ACP counts (#3817).";
136
136
  readonly "answer-in-steward-turn": "The answer was given during a steward's turn, or by a process it started: a steward never answers a decision point, and a person answers it through hud or at a shell.";
137
+ readonly "answer-never-over-mcp": "The answer or retraction came over MCP or ACP, or from a process a session on one started, and the question constrains a gate that is never resolved there: a person answers it at a shell or through hud (#3817).";
137
138
  readonly "answer-not-answered": "points retract names a question that has no answer to retract: it is escalated or proposed, and people answer it instead (#3351).";
138
139
  readonly "answer-field-unsupported": "The answer kind's copy of point-answer.schema.json predates a field the write needs, a note, a relay, a retraction or an ad-hoc question's asked: copy the schema anew to turn it on (#3351, #3402, #3403).";
139
140
  readonly "point-candidates-invalid": "points ask names an ad-hoc point without --candidates, a declared point with them, or candidates that are not a question and criteria of the point's question type (#3403).";
@@ -1 +1 @@
1
- {"version":3,"file":"reason-codes.d.ts","sourceRoot":"","sources":["../../src/workspace/reason-codes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reason-codes.d.ts","sourceRoot":"","sources":["../../src/workspace/reason-codes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant",
3
- "version": "0.124.0",
3
+ "version": "0.124.2",
4
4
  "description": "Declarative infrastructure-as-code toolkit — TypeScript on Node.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -28,7 +28,11 @@
28
28
  * `clientInfo`. Computed provenance, from git, is unchanged.
29
29
  *
30
30
  * Nothing here listens on a port or authenticates anyone (ws-052): the server
31
- * speaks over stdio, and `by` is recorded as given, as `--by` is.
31
+ * speaks over stdio, and `by` is recorded as given, as `--by` is. A decision
32
+ * point's answer is the exception (#3817): `chant serve mcp` makes every call
33
+ * the model's (`lifecycle/gate-origin.ts`), so `points-answer` and
34
+ * `points-retract` count nobody `by` names toward a point's quorum, as
35
+ * `op-approve` records its approver as an agent.
32
36
  *
33
37
  * An agent session (#2548): a server started with `CHANT_AGENT` set writes in
34
38
  * that session, bound to its one member, and its writes are refused outside
@@ -289,7 +293,7 @@ export const workspaceWriteTools: ToolDefinition[] = [
289
293
  {
290
294
  name: "points-answer",
291
295
  description:
292
- "Record people's answer to an open decision point question, or confirm a model's proposal: chant workspace points answer. Refused unless the point's quorum is met: distinct people, none holding the agent role, each holding one of the quorum's roles when it names any. An answered question never changes in place: points-retract takes it back. " +
296
+ "Record people's answer to an open decision point question, or confirm a model's proposal: chant workspace points answer. Refused unless the point's quorum is met: distinct people, none holding the agent role, each holding one of the quorum's roles when it names any. On a server started with `chant serve mcp`, every call is the model's, so nobody named in by counts toward the quorum (quorum-not-met), and a question whose gate is neverOverMcp is refused outright (answer-never-over-mcp): people answer at a shell or through hud. An answered question never changes in place: points-retract takes it back. " +
293
297
  PROTOCOL,
294
298
  inputSchema: {
295
299
  type: "object",
@@ -308,7 +312,7 @@ export const workspaceWriteTools: ToolDefinition[] = [
308
312
  {
309
313
  name: "points-retract",
310
314
  description:
311
- "Take back people's answer to a decision point question: chant workspace points retract. The question is escalated to people again, and the answer, who gave it and its note stay in the record's retractions with who retracted it, when and why. Refused unless the point's quorum is met, counted as for an answer. " +
315
+ "Take back people's answer to a decision point question: chant workspace points retract. The question is escalated to people again, and the answer, who gave it and its note stay in the record's retractions with who retracted it, when and why. Refused unless the point's quorum is met, counted as for an answer, so over MCP it is refused as an answer is. " +
312
316
  PROTOCOL,
313
317
  inputSchema: {
314
318
  type: "object",
@@ -84,6 +84,48 @@ describe("lifecycle/gate-audit", () => {
84
84
  expect(entries.filter((e) => e.kind === "approved")).toHaveLength(1);
85
85
  });
86
86
 
87
+ test("each ledger entry names its line: path, number and text as passed in", () => {
88
+ const text = `${pending()}\n\n${resolution()}\n`;
89
+ const { entries } = deriveGateAudit({ ledgers: [{ op: "tf-apply", path: "gates/tf.jsonl", lines: gateLedgerLines(text) }] });
90
+ expect(entries.map((e) => [e.source.path, e.source.line, e.source.text])).toEqual([
91
+ ["gates/tf.jsonl", 1, pending()],
92
+ ["gates/tf.jsonl", 3, resolution()],
93
+ ]);
94
+ const records = deriveGateAudit({ ledgers: [{ op: "tf-apply", lines: [{ record: JSON.parse(pending()) }, { record: JSON.parse(resolution()) }] }] });
95
+ expect(records.entries.map((e) => [e.source.line, e.source.text])).toEqual([[1, undefined], [2, undefined]]);
96
+ });
97
+
98
+ test("a caller's id replaces the default, and applies run under it", () => {
99
+ const ledgers = [ledger("tf-apply", pending(), resolution())];
100
+ const id = (e: { source: { path: string; text?: string }; kind: string; id: string }) => (e.source.text ? `mine:${e.source.path}:${e.source.text.length}` : e.id);
101
+ const plain = deriveGateAudit({ ledgers });
102
+ const { entries } = deriveGateAudit({ ledgers, id, applies: [{ ref: "reports/1", at: "2026-10-01T12:00:00.000Z", gate: "wave-1", digest: D1 }] });
103
+ const approved = entries.find((e) => e.kind === "approved")!;
104
+ expect(approved.id).toBe(`mine:_gates/tf-apply.jsonl:${resolution().length}`);
105
+ expect(entries.find((e) => e.kind === "applied")?.under).toBe(approved.id);
106
+ expect(plain.entries.map((e) => e.id)).not.toContain(approved.id);
107
+ });
108
+
109
+ test("an approval read from history names who committed it", () => {
110
+ const log = `\x1ec1\x1fmallory\x1f2026-10-01T11:05:00+00:00\x1fm@x.io\n\ndiff --git a/x b/x\n+${pending()}\n+${resolution()}\n`;
111
+ const lines = gateLedgerLinesFromLog(log);
112
+ expect(lines[1]).toEqual({ text: resolution(), commit: "c1", added: { at: "2026-10-01T11:05:00.000Z", by: "mallory", email: "m@x.io" } });
113
+ const { entries } = deriveGateAudit({ ledgers: [{ op: "tf-apply", lines }] });
114
+ const approved = entries.find((e) => e.kind === "approved")!;
115
+ expect(approved).toMatchObject({ by: "alex", committedBy: "mallory", source: { commit: "c1", author: { by: "mallory", email: "m@x.io", at: "2026-10-01T11:05:00.000Z" } } });
116
+ expect(entries.find((e) => e.kind === "approval-requested")?.source.author?.by).toBe("mallory");
117
+ const noEmail = gateLedgerLinesFromLog(`\x1ec2\x1fbo\x1f2026-10-01T11:05:00+00:00\n\n+${resolution()}\n`);
118
+ expect(noEmail[0]?.added).toEqual({ at: "2026-10-01T11:05:00.000Z", by: "bo" });
119
+ });
120
+
121
+ test("a sealed pull request approval is a review, with the seal beside it", () => {
122
+ const seal = { signer: "bot", signature: "-----BEGIN" };
123
+ const { entries } = deriveGateAudit({ ledgers: [ledger("tf-apply", pending(), resolution({ seal, via: "pr-review", pr: 4 }), resolution({ seal, timestamp: "2026-10-01T12:00:00.000Z" }))] });
124
+ const approved = entries.filter((e) => e.kind === "approved");
125
+ expect(approved.map((e) => [e.seal, e.sealed, e.signer])).toEqual([["review", true, "bot"], ["sealed", true, "bot"]]);
126
+ expect(approved[0]?.review).toEqual({ pr: 4 });
127
+ });
128
+
87
129
  test("applies: under an approval, without one, waived, and spending an override", () => {
88
130
  const ledgers = [ledger("tf-apply", pending(), resolution()), ledger("policy-override", resolution({ op: "policy-override", gate: "root/a", planDigest: "sha256:ov" }))];
89
131
  const ok = { ref: "reports/1", at: "2026-10-01T12:00:00.000Z", gate: "wave-1", digest: D1 };
@@ -47,6 +47,33 @@
47
47
  * - `override`: an apply cites an override that no line holds.
48
48
  * - `malformed-line`: a line that is not a gate record. Its content is lost
49
49
  * to the trail, so it is said.
50
+ *
51
+ * ## Sources and ids
52
+ *
53
+ * Every ledger entry's `source` names the line it came from: `path`, `line`
54
+ * (the line's own `line` when given, which {@link gateLedgerLines} fills
55
+ * with the file's line number, else its 1-based place in `ledger.lines`),
56
+ * and `text`, exactly as passed in, when the line was given as text. When the
57
+ * line came from {@link gateLedgerLinesFromLog}, `source.author` is the
58
+ * author of the commit that added it (or, for a revocation, removed it), and
59
+ * resolutions also carry it as `committedBy`. Under `approval: ledger` that
60
+ * is the only check on who pushed an approval: anyone who can push may write
61
+ * any `resolvedBy`.
62
+ *
63
+ * The default `id` is a digest over the source and the record. A product
64
+ * that already holds ids of its own (an append-only record whose ids
65
+ * customers keep) passes {@link GateAuditOptions.id}, which gets each entry
66
+ * with its default id and returns the id to use. `under` links follow it.
67
+ *
68
+ * ## Seal and review
69
+ *
70
+ * `seal` names how the approval came to be: `review` when the line came
71
+ * through a forge review (`via: "pr-review"`, or a `review` field), else
72
+ * `sealed` when it carries an ssh seal, else `unsigned`. A pull request
73
+ * approval that `chant approve` also sealed is still `review`: the review is
74
+ * what authorised it, and the seal attests who wrote the line. That fact is
75
+ * kept apart as `sealed: true` with its `signer`, on any entry whose line
76
+ * holds a seal. terragucci classifies the same way.
50
77
  */
51
78
  import { canonicalJson } from "../effect-receipt";
52
79
  import { contentDigest } from "../content-digest";
@@ -64,19 +91,29 @@ export const GATE_AUDIT_KINDS = [
64
91
  ] as const;
65
92
  export type GateAuditKind = (typeof GATE_AUDIT_KINDS)[number];
66
93
 
67
- /** How an approval was authenticated: an ssh seal, a forge review, or neither. */
94
+ /** How an approval was authorised: a forge review, an ssh seal, or neither. A review wins; a review that is also sealed has `sealed: true` beside it. */
68
95
  export type GateAuditSeal = "sealed" | "review" | "unsigned";
69
96
 
97
+ /** A commit that added or removed a ledger line: its date and its author's name and email. */
98
+ export interface GateLedgerCommit {
99
+ at: string;
100
+ by?: string;
101
+ email?: string;
102
+ }
103
+
70
104
  /**
71
105
  * One line of a ledger file. Give the `text` as it is on disk, or the parsed
72
- * `record` a {@link GateLedgerPort} returns. A line a commit removed carries
73
- * `removed`, with when and by whom (the commit's date and author).
106
+ * `record` a {@link GateLedgerPort} returns. `line` is its line number in the
107
+ * file, when known. A line read from history carries the commit that `added`
108
+ * it, or, if a commit removed it, `removed`, each with when and by whom.
74
109
  */
75
110
  export interface GateLedgerLine {
76
111
  text?: string;
77
112
  record?: unknown;
113
+ line?: number;
78
114
  commit?: string;
79
- removed?: { at: string; by?: string };
115
+ added?: GateLedgerCommit;
116
+ removed?: GateLedgerCommit;
80
117
  }
81
118
 
82
119
  /** One op's ledger file. */
@@ -111,7 +148,13 @@ export interface GateAuditSource {
111
148
  /** The ledger file, or the apply's `ref` for an apply. */
112
149
  path: string;
113
150
  op?: string;
151
+ /** Ledger entries: the line's `line`, else its 1-based place in the ledger's `lines`. */
152
+ line?: number;
153
+ /** Ledger entries: the line's text exactly as passed in, when it was passed as text. */
154
+ text?: string;
114
155
  commit?: string;
156
+ /** The commit that added the line, or for a revocation removed it, when the line came from history. */
157
+ author?: GateLedgerCommit;
115
158
  change: "added" | "removed" | "apply";
116
159
  }
117
160
 
@@ -127,10 +170,14 @@ export interface GateAuditEntry {
127
170
  digest?: string;
128
171
  /** Who: the approver or overrider, whoever removed the line, or for an apply, whoever ran it. */
129
172
  by?: string;
130
- /** Resolutions and revocations: sealed, reviewed, or unsigned. */
173
+ /** Resolutions and revocations: reviewed, sealed, or unsigned. */
131
174
  seal?: GateAuditSeal;
175
+ /** The line holds an ssh seal, whatever `seal` says (a sealed review is `seal: "review"`). */
176
+ sealed?: true;
132
177
  /** The ssh signer, when sealed. */
133
178
  signer?: string;
179
+ /** Resolutions read from history: the author of the commit that added the line, who may not be `by`. */
180
+ committedBy?: string;
134
181
  /** Who carried the approval to chant (`chant approve --relayed-by`). */
135
182
  relayedBy?: string;
136
183
  /** A person or an agent, and the roles claimed. */
@@ -168,6 +215,12 @@ export interface GateAuditOptions {
168
215
  isOverride?: (op: string, gate: string) => boolean;
169
216
  /** Whether approvals of a gate need a seal or a review. Default none. */
170
217
  sealed?: (op: string, gate: string) => boolean;
218
+ /**
219
+ * The id to give an entry, from the entry with its default id. Default
220
+ * that id. A product with ids of its own keys by `entry.source` (its
221
+ * `path`, `line`, `text`). `under` refers to the ids this returns.
222
+ */
223
+ id?: (entry: GateAuditEntry) => string;
171
224
  }
172
225
 
173
226
  export interface GateAuditInput extends GateAuditOptions {
@@ -205,11 +258,11 @@ function rowOf(line: GateLedgerLine): Row | undefined {
205
258
  return v && typeof v === "object" && !Array.isArray(v) ? (v as Row) : undefined;
206
259
  }
207
260
 
208
- function sealOf(r: Row): { seal: GateAuditSeal; signer?: string } {
261
+ function sealOf(r: Row): { seal: GateAuditSeal; sealed?: true; signer?: string } {
209
262
  const s = r.seal as { signature?: unknown; signer?: unknown } | null | undefined;
210
- if (s && s.signature) return { seal: "sealed", ...(str(s.signer) ? { signer: str(s.signer) } : {}) };
211
- if (r.review || r.via === "pr-review") return { seal: "review" };
212
- return { seal: "unsigned" };
263
+ const signed = s && s.signature ? { sealed: true as const, ...(str(s.signer) ? { signer: str(s.signer) } : {}) } : undefined;
264
+ if (r.review || r.via === "pr-review") return { seal: "review", ...signed };
265
+ return signed ? { seal: "sealed", ...signed } : { seal: "unsigned" };
213
266
  }
214
267
 
215
268
  function reviewOf(r: Row): GateAuditEntry["review"] {
@@ -246,13 +299,15 @@ const compatible = (a: string | undefined, b: string | undefined): boolean => a
246
299
  /** The entries `input` adds up to, oldest first, and the gaps they show. */
247
300
  export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntry[]; gaps: GateAuditGap[] } {
248
301
  const isOverride = input.isOverride ?? isOverrideGate;
302
+ const rekey = input.id;
303
+ const keyed = (e: GateAuditEntry): GateAuditEntry => (rekey ? { ...e, id: rekey(e) } : e);
249
304
  const entries: GateAuditEntry[] = [];
250
305
  const gaps: GateAuditGap[] = [];
251
306
 
252
307
  for (const ledger of input.ledgers) {
253
308
  const path = ledger.path ?? `_gates/${ledger.op}.jsonl`;
254
- const parsed: { line: GateLedgerLine; r: Row; pending: boolean }[] = [];
255
- for (const line of ledger.lines) {
309
+ const parsed: { line: GateLedgerLine; n: number; r: Row; pending: boolean }[] = [];
310
+ for (const [i, line] of ledger.lines.entries()) {
256
311
  const r = rowOf(line);
257
312
  const pending = r?.kind === "pending";
258
313
  const ok = r && r.version === 1 && typeof r.gate === "string" && typeof r.timestamp === "string" && (pending || typeof r.resolvedBy === "string");
@@ -260,7 +315,7 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
260
315
  gaps.push({ kind: "malformed-line", op: ledger.op, detail: `${path} holds a line that is not a gate record${line.commit ? ` (commit ${line.commit})` : ""}: ${(line.text ?? JSON.stringify(line.record) ?? "").slice(0, 80)}` });
261
316
  continue;
262
317
  }
263
- parsed.push({ line, r, pending });
318
+ parsed.push({ line, n: line.line ?? i + 1, r, pending });
264
319
  }
265
320
 
266
321
  // Each denial an override answers: the newest pending fact of its gate and digest.
@@ -273,53 +328,63 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
273
328
  requests.push({ op: ledger.op, gate: String(p.r.gate), at: time(String(p.r.timestamp)), ...(digest ? { digest } : {}), ...(str(p.r.environment) ? { environment: str(p.r.environment) } : {}) });
274
329
  }
275
330
 
276
- for (const { line, r, pending } of parsed) {
331
+ for (const { line, n, r, pending } of parsed) {
277
332
  const gate = String(r.gate);
278
333
  const override = isOverride(ledger.op, gate);
279
334
  const removed = line.removed;
280
335
  if (pending && removed) continue;
281
336
  const digest = str(r.planDigest);
282
- const source: GateAuditSource = { path, op: ledger.op, ...(line.commit ? { commit: line.commit } : {}), change: removed ? "removed" : "added" };
337
+ const author = removed ?? line.added;
338
+ const source: GateAuditSource = {
339
+ path,
340
+ op: ledger.op,
341
+ line: n,
342
+ ...(line.text !== undefined ? { text: line.text } : {}),
343
+ ...(line.commit ? { commit: line.commit } : {}),
344
+ ...(author ? { author } : {}),
345
+ change: removed ? "removed" : "added",
346
+ };
283
347
  const id = idOf(removed ? "removed" : "ledger", path, line.commit ?? null, r);
284
348
  const extra = Object.fromEntries(Object.entries(r).filter(([k]) => !KNOWN.has(k)));
285
349
  const base = { id, gate, op: ledger.op, ...(digest ? { digest } : {}), source } as const;
286
350
 
287
351
  if (pending) {
288
- entries.push({
352
+ entries.push(keyed({
289
353
  ...base,
290
354
  kind: override ? "override-requested" : "approval-requested",
291
355
  at: String(r.timestamp),
292
356
  ...drop({ runId: str(r.runId), expiresAt: str(r.expiresAt), description: str(r.description), url: str(r.url), rules: strings(r.rules) }),
293
357
  detail: extra,
294
- });
358
+ }));
295
359
  continue;
296
360
  }
297
361
 
298
- const { seal, signer } = sealOf(r);
362
+ const { seal, sealed, signer } = sealOf(r);
299
363
  if (removed) {
300
- entries.push({
364
+ entries.push(keyed({
301
365
  ...base,
302
366
  kind: "revoked",
303
367
  at: removed.at,
304
368
  ...(removed.by ? { by: removed.by } : {}),
305
369
  subject: override ? "override" : "approval",
306
370
  seal,
371
+ ...(sealed ? { sealed } : {}),
307
372
  detail: { ...extra, approvedBy: r.resolvedBy, approvedAt: r.timestamp, ...(signer ? { signer } : {}) },
308
- });
373
+ }));
309
374
  continue;
310
375
  }
311
376
 
312
377
  const denial = override ? denials.get(`${gate}\n${digest ?? ""}`) : undefined;
313
378
  const rules = strings(denial?.rules) ?? (override && gate.startsWith("override-") ? [gate.slice("override-".length)] : undefined);
314
- const entry: GateAuditEntry = {
379
+ const entry: GateAuditEntry = keyed({
315
380
  ...base,
316
381
  kind: override ? "override-recorded" : "approved",
317
382
  at: String(r.timestamp),
318
383
  by: String(r.resolvedBy),
319
384
  seal,
320
- ...drop({ signer, relayedBy: str(r.relayedBy), approver: approverOf(r), note: str(r.note), url: str(r.url), review: reviewOf(r), rules }),
385
+ ...drop({ sealed, signer, committedBy: line.added?.by, relayedBy: str(r.relayedBy), approver: approverOf(r), note: str(r.note), url: str(r.url), review: reviewOf(r), rules }),
321
386
  detail: extra,
322
- };
387
+ });
323
388
  entries.push(entry);
324
389
 
325
390
  if (!override) {
@@ -349,7 +414,7 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
349
414
  if (a.digest !== undefined && a.approval !== "not-required" && !approval) {
350
415
  gaps.push({ kind: "approval", ...(a.op ? { op: a.op } : {}), gate: a.gate, digest: a.digest, detail: `${a.ref} applied under ${a.digest}, but the ledger holds no approval of ${a.gate} for that digest before ${a.at}` });
351
416
  }
352
- entries.push({
417
+ entries.push(keyed({
353
418
  ...base,
354
419
  id: idOf("apply", a.ref, a.at, a.gate, a.digest ?? null),
355
420
  kind: "applied",
@@ -357,7 +422,7 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
357
422
  ...(a.by ? { by: a.by } : {}),
358
423
  ...(approval ? { under: approval.id } : {}),
359
424
  detail: { ...(a.detail ?? {}), approval: a.approval ?? "required" },
360
- });
425
+ }));
361
426
 
362
427
  for (const o of a.overrides ?? []) {
363
428
  const recorded = find("override-recorded", o.gate, o.digest, false);
@@ -365,7 +430,7 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
365
430
  gaps.push({ kind: "override", ...(a.op ? { op: a.op } : {}), gate: o.gate, ...(o.digest ? { digest: o.digest } : {}), detail: `${a.ref} cites the override ${o.gate}${o.digest ? ` for ${o.digest}` : ""}, but the ledger holds none` });
366
431
  continue;
367
432
  }
368
- entries.push({
433
+ entries.push(keyed({
369
434
  ...base,
370
435
  id: idOf("spent", a.ref, a.at, recorded.id),
371
436
  kind: "override-spent",
@@ -375,7 +440,7 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
375
440
  ...(recorded.digest ? { digest: recorded.digest } : {}),
376
441
  under: recorded.id,
377
442
  detail: {},
378
- });
443
+ }));
379
444
  }
380
445
  }
381
446
 
@@ -383,24 +448,26 @@ export function deriveGateAudit(input: GateAuditInput): { entries: GateAuditEntr
383
448
  return { entries, gaps };
384
449
  }
385
450
 
386
- /** The lines of one ledger file's text, all added. Blank lines are skipped. */
451
+ /** The lines of one ledger file's text, all added, each with its line number. Blank lines are skipped. */
387
452
  export function gateLedgerLines(content: string): GateLedgerLine[] {
388
- return content.split("\n").map((l) => l.trim()).filter(Boolean).map((text) => ({ text }));
453
+ return content.split("\n").flatMap((l, i) => (l.trim() ? [{ text: l.trim(), line: i + 1 }] : []));
389
454
  }
390
455
 
391
456
  /**
392
457
  * The lines each commit added to and removed from a ledger file, oldest first,
393
458
  * from `git log -p --unified=0 --no-renames` written with
394
- * `--format=%x1e%H%x1f%an%x1f%aI` over the file. The caller runs git; this
395
- * reads the text. A line removed and added again in one commit (a newline
396
- * fixed at the end of the file) is neither. A removed line is what
397
- * {@link deriveGateAudit} reports as a revocation.
459
+ * `--format=%x1e%H%x1f%an%x1f%aI` over the file (append `%x1f%ae` for the
460
+ * author's email). The caller runs git; this reads the text. Each line keeps
461
+ * its commit and that commit's date and author, as `added` or `removed`. A
462
+ * line removed and added again in one commit (a newline fixed at the end of
463
+ * the file) is neither. A removed line is what {@link deriveGateAudit}
464
+ * reports as a revocation.
398
465
  */
399
466
  export function gateLedgerLinesFromLog(log: string): GateLedgerLine[] {
400
467
  const out: GateLedgerLine[] = [];
401
468
  for (const block of log.split("\x1e").slice(1)) {
402
469
  const [head = "", ...rest] = block.split("\n");
403
- const [commit = "", author = "", date = ""] = head.split("\x1f");
470
+ const [commit = "", author = "", date = "", email = ""] = head.split("\x1f");
404
471
  const net = new Map<string, number>();
405
472
  const order: string[] = [];
406
473
  for (const l of rest) {
@@ -412,10 +479,11 @@ export function gateLedgerLinesFromLog(log: string): GateLedgerLine[] {
412
479
  }
413
480
  const when = Date.parse(date.trim());
414
481
  const at = Number.isNaN(when) ? date.trim() : new Date(when).toISOString();
482
+ const by: GateLedgerCommit = { at, ...(author ? { by: author } : {}), ...(email.trim() ? { email: email.trim() } : {}) };
415
483
  for (const text of order) {
416
484
  const n = net.get(text)!;
417
485
  for (let i = 0; i < Math.abs(n); i++) {
418
- out.push(n > 0 ? { text, commit: commit.trim() } : { text, commit: commit.trim(), removed: { at, ...(author ? { by: author } : {}) } });
486
+ out.push({ text, commit: commit.trim(), ...(n > 0 ? { added: { ...by } } : { removed: { ...by } }) });
419
487
  }
420
488
  }
421
489
  }
@@ -66,23 +66,40 @@ export const UNATTESTED_APPROVER = "unattested";
66
66
 
67
67
  let ambient: GateOrigin = "cli";
68
68
 
69
+ /**
70
+ * The environment variable a model-authored channel carries into child
71
+ * processes (chant#3817), as a steward's turn carries `CHANT_STEWARD`: a
72
+ * `chant workspace points answer` or `chant approve` a process on MCP or ACP
73
+ * starts is that channel's too. Only `mcp` and `acp` are read from it, so it
74
+ * can make a process model-authored and never make one a person's.
75
+ */
76
+ export const GATE_ORIGIN_ENV = "CHANT_GATE_ORIGIN";
77
+
69
78
  /**
70
79
  * Declare the channel this process serves. Called once at an entry point, not
71
80
  * per call: `chant mcp` sets `"mcp"` before it serves anything, `chant acp`
72
- * sets `"acp"`, and the CLI leaves the default.
81
+ * sets `"acp"`, and the CLI leaves the default. A model-authored channel is
82
+ * also exported as {@link GATE_ORIGIN_ENV}, so a child process knows it too.
73
83
  */
74
84
  export function setGateOrigin(origin: GateOrigin): void {
75
85
  ambient = origin;
86
+ if (isModelAuthored(origin)) process.env[GATE_ORIGIN_ENV] = origin;
76
87
  }
77
88
 
78
- /** The channel this process serves. `"cli"` unless an entry point said otherwise. */
89
+ /**
90
+ * The channel this process serves. `"cli"` unless an entry point said
91
+ * otherwise, or this process was started by one on MCP or ACP.
92
+ */
79
93
  export function currentGateOrigin(): GateOrigin {
80
- return ambient;
94
+ if (ambient !== "cli") return ambient;
95
+ const inherited = process.env[GATE_ORIGIN_ENV];
96
+ return inherited === "mcp" || inherited === "acp" ? inherited : ambient;
81
97
  }
82
98
 
83
99
  /** Restore the default. For tests, which must not leak a channel into each other. */
84
100
  export function resetGateOrigin(): void {
85
101
  ambient = "cli";
102
+ delete process.env[GATE_ORIGIN_ENV];
86
103
  }
87
104
 
88
105
  /**
@@ -0,0 +1,161 @@
1
+ /**
2
+ * #3817: a gate that asks a decision point is not passed by an answer sent
3
+ * over MCP or ACP. The answer there is an agent's, so nobody it names counts
4
+ * toward a human quorum and the gate keeps waiting; a question whose gate is
5
+ * `neverOverMcp` is refused outright. The same answer from a shell answers
6
+ * it, and the next run passes.
7
+ *
8
+ * The workspace is real (a git repository with the reference workspace's
9
+ * answer kind, a points file and a trust policy at base). The MCP answer goes
10
+ * through the `points-answer` tool's own handler with this process serving
11
+ * MCP, the shell answer through `runWorkspacePoints`. The gate ledger the run
12
+ * writes is the in-memory port; the `neverOverMcp` pending fact is on the
13
+ * workspace's own `chant/lifecycle`, where `points answer` reads it.
14
+ */
15
+
16
+ import { writeFileSync, mkdirSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
19
+ import { cleanScratch, git, workspace } from "../workspace/__fixtures__/decide-workspace";
20
+ import { runWorkspacePoints } from "../workspace/points-cli";
21
+ import type { CommandContext } from "../cli/registry";
22
+ import { createWorkspaceTools } from "../cli/mcp/workspace-tools";
23
+ import { GATE_ORIGIN_ENV, resetGateOrigin, setGateOrigin } from "../lifecycle/gate-origin";
24
+ import { appendPendingGate } from "../lifecycle/gate-ledger";
25
+ import { ApplyOp } from "./composites/apply-op";
26
+ import { memoryGateLedgerPort } from "./gate";
27
+ import { runOpLocally } from "./local-executor";
28
+ import type { ActivityFn } from "./activity-registry";
29
+ import type { OpConfig } from "./types";
30
+
31
+ const PLAN = `jcs1-sha256:${"3".repeat(64)}`;
32
+
33
+ const POINTS = {
34
+ points: {
35
+ "prod-apply": {
36
+ title: "Apply this plan to prod",
37
+ question: { type: "noul", instructions: "Should this plan be applied to prod?", criteria: { true: "Apply it.", false: "Do not apply it." } },
38
+ inputs: { "gate.component": "the Op the gate belongs to", "gate.planDigest": "the plan the gate binds" },
39
+ deciders: [{ kind: "quorum", count: 2, roles: ["lead"] }],
40
+ },
41
+ },
42
+ };
43
+
44
+ let root: string;
45
+ const applied: string[] = [];
46
+ const activities = new Map<string, ActivityFn>([
47
+ ["chantBuild", async () => ({ ok: true })],
48
+ ["lifecycleDiff", async () => ({ planDigest: PLAN, drifted: true })],
49
+ ["nativeApply", async () => {
50
+ applied.push(PLAN);
51
+ return { ok: true };
52
+ }],
53
+ ]);
54
+
55
+ const config = (name: string): OpConfig =>
56
+ (ApplyOp({ name, env: "prod", target: "kubectl", gate: { gate: "approve-apply", point: "prod-apply" } }).op as unknown as { props: OpConfig }).props;
57
+
58
+ type Doc = Record<string, unknown> & { error?: { code: string; message: string } };
59
+
60
+ /** The `points-answer` and `points-retract` tools, as `chant serve mcp` serves them in the workspace. */
61
+ function mcpTool(name: "points-answer" | "points-retract"): (params: Record<string, unknown>) => Promise<Doc> {
62
+ const tool = createWorkspaceTools({ cwd: root }).find((t) => t.definition.name === name)!;
63
+ return async (params) => (await tool.handler(params, {} as never)) as Doc;
64
+ }
65
+
66
+ /** `chant workspace points <verb> <id> ...` through the command's handler, in the workspace. Returns the document it prints. */
67
+ async function shell(verb: "answer" | "retract", id: string, by: string[], answer?: string): Promise<Doc> {
68
+ const printed: string[] = [];
69
+ const log = vi.spyOn(console, "log").mockImplementation((line: unknown) => {
70
+ printed.push(String(line));
71
+ });
72
+ const err = vi.spyOn(console, "error").mockImplementation(() => {});
73
+ const was = process.cwd();
74
+ process.chdir(root);
75
+ try {
76
+ const ctx = { args: { extraPositional: verb, extraPositional2: id, ...(answer !== undefined ? { answer } : {}), bys: by, json: true }, plugins: [], serializers: [] } as unknown as CommandContext;
77
+ await runWorkspacePoints(ctx);
78
+ } finally {
79
+ process.chdir(was);
80
+ log.mockRestore();
81
+ err.mockRestore();
82
+ }
83
+ return JSON.parse(printed.join("\n")) as Doc;
84
+ }
85
+
86
+ beforeAll(() => {
87
+ root = workspace(POINTS);
88
+ mkdirSync(join(root, ".chant"), { recursive: true });
89
+ writeFileSync(join(root, ".chant", "trust.json"), JSON.stringify({ schema: 1, roles: { agent: ["bot"], lead: ["alice", "bob"] } }));
90
+ git(root, "add", "-A");
91
+ git(root, "commit", "-q", "-m", "trust");
92
+ });
93
+
94
+ afterEach(() => resetGateOrigin());
95
+ afterAll(cleanScratch);
96
+
97
+ describe("an answer over MCP or ACP never passes a gate that needs a human quorum (#3817)", () => {
98
+ test("points-answer over MCP naming the quorum's people does not answer; the gate keeps waiting; the same answer from a shell passes it", async () => {
99
+ const port = memoryGateLedgerPort();
100
+ const op = config("prod-apply");
101
+
102
+ const first = await runOpLocally(op, activities, {}, undefined, { gates: port, cwd: root, now: "2026-10-11T10:00:00.000Z" });
103
+ expect(first.status).toBe("waiting");
104
+ const id = first.point!.id;
105
+
106
+ // This process now serves MCP: alice and bob both hold lead, and neither counts.
107
+ setGateOrigin("mcp");
108
+ const overMcp = await mcpTool("points-answer")({ id, answer: true, by: ["alice", "bob"] });
109
+ expect(overMcp.error?.code).toBe("quorum-not-met");
110
+ expect(overMcp.error?.message).toContain("alice, who was named over MCP");
111
+ expect(overMcp.error?.message).toContain("bob, who was named over MCP");
112
+
113
+ // ACP is the same, and so is `chant workspace points answer` in a process a session on either started.
114
+ setGateOrigin("acp");
115
+ expect((await mcpTool("points-answer")({ id, answer: true, by: ["alice", "bob"] })).error?.code).toBe("quorum-not-met");
116
+ resetGateOrigin();
117
+ process.env[GATE_ORIGIN_ENV] = "mcp";
118
+ expect((await shell("answer", id, ["alice", "bob"], "yes")).error?.code).toBe("quorum-not-met");
119
+ resetGateOrigin();
120
+
121
+ const still = await runOpLocally(op, activities, {}, undefined, { gates: port, cwd: root, now: "2026-10-11T10:05:00.000Z" });
122
+ expect(still.status).toBe("waiting");
123
+ expect(still.point?.id).toBe(id);
124
+ expect(applied).toEqual([]);
125
+ expect(port.resolved).toHaveLength(0);
126
+
127
+ // From a shell the same people answer it, and the next run passes on the answer.
128
+ const answered = await shell("answer", id, ["alice", "bob"], "yes");
129
+ expect(answered).toMatchObject({ verb: "answer", id, written: true, question: { state: "answered", answer: true, answeredBy: ["alice", "bob"] } });
130
+ const passed = await runOpLocally(op, activities, {}, undefined, { gates: port, cwd: root, now: "2026-10-11T10:10:00.000Z" });
131
+ expect(passed.status).toBe("ok");
132
+ expect(applied).toEqual([PLAN]);
133
+
134
+ // Taking the answer back follows the same rule.
135
+ setGateOrigin("mcp");
136
+ expect((await mcpTool("points-retract")({ id, by: ["alice", "bob"] })).error?.code).toBe("quorum-not-met");
137
+ });
138
+
139
+ test("a question whose gate is neverOverMcp is refused over MCP outright, and answered from a shell", async () => {
140
+ const port = memoryGateLedgerPort();
141
+ const op = config("tf-apply");
142
+
143
+ const first = await runOpLocally(op, activities, {}, undefined, { gates: port, cwd: root, now: "2026-10-11T11:00:00.000Z" });
144
+ expect(first.status).toBe("waiting");
145
+ const id = first.point!.id;
146
+ // The gate's pending fact on chant/lifecycle says it is never resolved over MCP, as terragucci's tf-apply records it.
147
+ await appendPendingGate({ op: "tf-apply", gate: "approve-apply", timestamp: "2026-10-11T11:00:00.000Z", expiresAt: "2026-10-13T11:00:00.000Z", planDigest: PLAN, neverOverMcp: true, answer: { point: "prod-apply", id, path: first.point!.path } }, { cwd: root });
148
+
149
+ setGateOrigin("mcp");
150
+ const overMcp = await mcpTool("points-answer")({ id, answer: true, by: ["alice", "bob"] });
151
+ expect(overMcp.error?.code).toBe("answer-never-over-mcp");
152
+ expect(overMcp.error?.message).toContain('gate "approve-apply" on "tf-apply"');
153
+ resetGateOrigin();
154
+
155
+ const answered = await shell("answer", id, ["alice", "bob"], "yes");
156
+ expect(answered).toMatchObject({ verb: "answer", id, written: true, question: { state: "answered" } });
157
+
158
+ setGateOrigin("acp");
159
+ expect((await mcpTool("points-retract")({ id, by: ["alice", "bob"] })).error?.code).toBe("answer-never-over-mcp");
160
+ });
161
+ });
@@ -157,7 +157,9 @@ export interface OpWaveHookOutcome {
157
157
  /** The run, for a `perRun` hook. */
158
158
  target?: string;
159
159
  exit: number;
160
- outcome: "passed" | "failed" | "held";
160
+ outcome: "passed" | "failed" | "held" | "skipped";
161
+ /** Why the moment was skipped, for `skipped` (#3811). */
162
+ reason?: string;
161
163
  }
162
164
 
163
165
  /** One run as a hook sees it (#3804). */
@@ -640,18 +642,25 @@ export function readOpWaveHooksFile(path: string | undefined = process.env.CHANT
640
642
  * Each call adds its outcomes to the file's `result` (`CHANT_HOOKS_RESULT`),
641
643
  * which chant reads back after the apply exits: the outcomes join the wave's
642
644
  * result and decision record, and a hold makes the wave wait for, or find,
643
- * an approval of its digest. `exec` runs one hook; inject it to run a hook
645
+ * an approval of its digest. `skip: "<reason>"` runs nothing and records the
646
+ * moment as skipped with the reason (#3811), for an apply that changes nothing:
647
+ * chant counts the moment as handled. A skip without a reason throws. `exec` runs one hook; inject it to run a hook
644
648
  * in process or to keep its output.
645
649
  */
646
650
  export function runOpWaveApplyHooks(
647
651
  file: OpWaveHooksFile,
648
652
  moment: OpWaveHookMoment,
649
- options: { cwd?: string; exec?: OpWaveExec; log?: (line: string) => void } = {},
653
+ options: { cwd?: string; exec?: OpWaveExec; log?: (line: string) => void; skip?: string } = {},
650
654
  ): OpWaveApplyHooksRun {
651
655
  const cwd = options.cwd ?? process.cwd();
652
656
  const log = options.log ?? ((line: string) => console.error(line));
653
657
  let run: OpWaveApplyHooksRun;
654
- if (file.refused) {
658
+ if (options.skip !== undefined) {
659
+ const reason = options.skip.trim();
660
+ if (!reason) throw new Error(`skipping the ${moment} hooks needs a reason (skip: "nothing to apply")`);
661
+ log(`${moment} hooks skipped: ${reason}`);
662
+ run = { moment, outcomes: [{ moment, name: "skip", exit: 0, outcome: "skipped", reason }], held: [], proceed: true };
663
+ } else if (file.refused) {
655
664
  log(`${file.refused}, so none of the ${moment} hooks run and the apply does not go on`);
656
665
  run = { moment, outcomes: [], held: [file.refused], proceed: false };
657
666
  } else {
@@ -616,6 +616,36 @@ describe("apply-stage hooks run by the apply, under its lock (#3804)", () => {
616
616
  h.done();
617
617
  });
618
618
 
619
+ test("an apply that skips both moments for an empty run exits the wave ok, and the skip is recorded (#3811)", async () => {
620
+ const h = harness(spec);
621
+ const exec: OpWaveExec = (argv, dir, env) => {
622
+ if (argv[1] === "plan") writeFileSync(join(dir, argv[3]!), JSON.stringify({ planDigest: digest("1") }));
623
+ if (argv[1] === "apply") {
624
+ const file = readOpWaveHooksFile(env?.CHANT_HOOKS, dir)!;
625
+ runOpWaveApplyHooks(file, "before-apply", { cwd: dir, skip: "nothing to apply", log: () => {} });
626
+ runOpWaveApplyHooks(file, "after-apply", { cwd: dir, skip: "nothing to apply", log: () => {} });
627
+ }
628
+ return 0;
629
+ };
630
+ const result = await runOpWave({ spec, specFile: "waves.json", wave: 1, cwd: h.cwd, exec, show: h.show, gates: memoryGateLedgerPort(), log: () => {} });
631
+ expect(result).toMatchObject({ exitCode: 0, applied: ["t1"] });
632
+ const skipped = [
633
+ { moment: "before-apply", name: "skip", exit: 0, outcome: "skipped", reason: "nothing to apply" },
634
+ { moment: "after-apply", name: "skip", exit: 0, outcome: "skipped", reason: "nothing to apply" },
635
+ ];
636
+ expect(result.hooks.filter((o) => o.outcome === "skipped")).toEqual(skipped);
637
+ expect(h.record().outcomes).toEqual(expect.arrayContaining(skipped));
638
+ h.done();
639
+ });
640
+
641
+ test("a skip with no reason is refused", () => {
642
+ const h = harness(spec);
643
+ writeFileSync(join(h.cwd, "waves.json"), JSON.stringify(spec));
644
+ const file = opWaveHooksAtBase({ specFile: "waves.json", wave: "prod", cwd: h.cwd, show: h.show });
645
+ expect(() => runOpWaveApplyHooks(file, "before-apply", { cwd: h.cwd, skip: " ", log: () => {} })).toThrow(/needs a reason/);
646
+ h.done();
647
+ });
648
+
619
649
  test("an apply outside the waves reads the same hooks at base and runs them itself; a hold stops it", () => {
620
650
  const h = harness(spec);
621
651
  writeFileSync(join(h.cwd, "waves.json"), JSON.stringify({ ...spec, hooks: undefined, waves: [{ ...spec.waves[0]!, hooks: undefined }] }));
@@ -93,6 +93,7 @@ import { IdentityError, refuseUnidentified } from "./identity";
93
93
  import { scopeSource } from "./write-scope";
94
94
  import { RefCASConflictError } from "../lifecycle/git";
95
95
  import { readLedgerAnswers, refreshLedger, withLedgerAnswers, writeLedgerAnswer, type LedgerAnswers } from "./answers-ledger";
96
+ import { currentGateOrigin, isModelAuthored, type GateOrigin } from "../lifecycle/gate-origin";
96
97
 
97
98
  /** The version of the write documents `points ask`, `points answer` and `points retract` print. */
98
99
  export const POINTS_WRITE_CONTRACT_VERSION = 1;
@@ -122,6 +123,8 @@ export const POINTS_WRITE_ERROR_CODES = [
122
123
  "record-id-taken",
123
124
  /** The answer was given during a steward's turn (#2749): a steward never answers a question, its own or another's. */
124
125
  "answer-in-steward-turn",
126
+ /** The answer or retraction came over MCP or ACP, and the question constrains a gate that is never resolved there (#3817). */
127
+ "answer-never-over-mcp",
125
128
  /** An answerer is named by a bare name, and identity.attribution at base is identified (#3163). */
126
129
  "principal-unidentified",
127
130
  /** `points retract` names a question that has no answer: escalated or proposed (#3351). */
@@ -715,6 +718,13 @@ export interface AnswerPointOptions {
715
718
  kind?: string;
716
719
  on?: string;
717
720
  dryRun?: boolean;
721
+ /**
722
+ * The channel the answer came through (#3817). Defaults to this process's
723
+ * (`currentGateOrigin`). Over MCP or ACP nobody `by` names counts toward
724
+ * the quorum, and a question that constrains a `neverOverMcp` gate is
725
+ * refused outright.
726
+ */
727
+ origin?: GateOrigin;
718
728
  }
719
729
 
720
730
  /**
@@ -821,20 +831,83 @@ async function findQuestion(cwd: string, kind: string | undefined, id: string):
821
831
  throw new PointsWriteError("record-not-found", `no answer record has id ${id}`);
822
832
  }
823
833
 
824
- /** Count `by` toward the point's quorum, or refuse with `quorum-not-met`. */
825
- function meetQuorum(name: string, by: string[], quorum: { count: number; roles?: string[] }, root: string, steward: string | undefined, verb: "answer" | "retract"): { counted: string[] } {
826
- const tally = tallyQuorum(by, quorum, policyFor(root), steward);
834
+ /** A model-authored channel's name, as a person reads it. */
835
+ const channelName = (origin: GateOrigin): string => (origin === "acp" ? "ACP" : "MCP");
836
+
837
+ /**
838
+ * Count `by` toward the point's quorum, or refuse with `quorum-not-met`.
839
+ *
840
+ * Over MCP or ACP (#3817) the names are the model's to choose, as a gate's
841
+ * approver is (`lifecycle/gate-origin.ts`), so the answer is an agent's and
842
+ * nobody it names counts: a person answers at a shell or through hud.
843
+ */
844
+ function meetQuorum(name: string, by: string[], quorum: { count: number; roles?: string[] }, root: string, steward: string | undefined, verb: "answer" | "retract", origin: GateOrigin): { counted: string[] } {
845
+ const overModel = isModelAuthored(origin);
846
+ const tally = overModel
847
+ ? { counted: [] as string[], left: by.map((n) => ({ name: n, why: `was named over ${channelName(origin)}, where an answer is an agent's` })), met: false }
848
+ : tallyQuorum(by, quorum, policyFor(root), steward);
827
849
  if (!tally.met) {
828
850
  const got = tally.counted.length;
829
851
  const left = tally.left.length ? `; not counted: ${tally.left.map((l) => `${l.name}, who ${l.why}`).join("; ")}` : "";
852
+ const remedy = overModel ? `: a person ${verb === "answer" ? "answers" : "retracts it"} at a shell with \`chant workspace points ${verb}\`, or through hud` : "";
830
853
  throw new PointsWriteError(
831
854
  "quorum-not-met",
832
- `${name} needs ${quorum.count} ${quorum.count === 1 ? "person" : "people"}${quorum.roles ? ` holding ${quorum.roles.join(" or ")}` : ""} to ${verb === "answer" ? "answer" : "retract an answer"}, and ${got} ${got === 1 ? "counts" : "count"}${got ? ` (${tally.counted.join(", ")})` : ""}${left}`,
855
+ `${name} needs ${quorum.count} ${quorum.count === 1 ? "person" : "people"}${quorum.roles ? ` holding ${quorum.roles.join(" or ")}` : ""} to ${verb === "answer" ? "answer" : "retract an answer"}, and ${got} ${got === 1 ? "counts" : "count"}${got ? ` (${tally.counted.join(", ")})` : ""}${left}${remedy}`,
833
856
  );
834
857
  }
835
858
  return tally;
836
859
  }
837
860
 
861
+ /** The gates a question's `constrains` names, as `gate:<op>/<gate>` with an optional `@<env>` (`op/gate-point.ts`'s `gateSubject`). */
862
+ function constrainedGates(d: Record<string, unknown>): { op: string; gate: string }[] {
863
+ const out: { op: string; gate: string }[] = [];
864
+ for (const c of Array.isArray(d.constrains) ? d.constrains : []) {
865
+ if (typeof c !== "string" || !c.startsWith("gate:")) continue;
866
+ const rest = c.slice("gate:".length);
867
+ const at = rest.lastIndexOf("@");
868
+ const named = at > 0 ? rest.slice(0, at) : rest;
869
+ const slash = named.indexOf("/");
870
+ if (slash > 0 && slash < named.length - 1) out.push({ op: named.slice(0, slash), gate: named.slice(slash + 1) });
871
+ }
872
+ return out;
873
+ }
874
+
875
+ /**
876
+ * Refuse an answer or retraction over MCP or ACP to a question that
877
+ * constrains a gate never resolved there (#3817, #3485): the gate-only op
878
+ * names chant knows, a pending fact on the gate ledger that says so (as
879
+ * terragucci's records do), or the Op's own `neverOverMcp`. `op-approve`
880
+ * refuses the same gates.
881
+ */
882
+ async function refuseNeverOverMcp(id: string, d: Record<string, unknown>, root: string, origin: GateOrigin, does: "answers" | "retracts"): Promise<void> {
883
+ if (!isModelAuthored(origin)) return;
884
+ const gates = constrainedGates(d);
885
+ if (gates.length === 0) return;
886
+ const { isNeverOverMcpGateOp } = await import("../op/gate-name");
887
+ const { readGateLedger } = await import("../lifecycle/gate-ledger");
888
+ let configs: Map<string, { config: { neverOverMcp?: boolean } }> | undefined;
889
+ for (const { op, gate } of gates) {
890
+ let never = isNeverOverMcpGateOp(op);
891
+ if (!never) {
892
+ const { pending } = await readGateLedger(op, { cwd: root }).catch(() => ({ pending: [] as { gate: string; neverOverMcp?: true }[] }));
893
+ never = pending.some((p) => p.gate === gate && p.neverOverMcp === true);
894
+ }
895
+ if (!never) {
896
+ if (configs === undefined) {
897
+ const { discoverOps } = await import("../op/discover");
898
+ configs = await discoverOps({ cwd: root }).then((r) => r.ops as Map<string, { config: { neverOverMcp?: boolean } }>).catch(() => new Map());
899
+ }
900
+ never = Boolean(configs.get(op)?.config.neverOverMcp);
901
+ }
902
+ if (never) {
903
+ throw new PointsWriteError(
904
+ "answer-never-over-mcp",
905
+ `${id} constrains gate "${gate}" on "${op}", which is never resolved over ${channelName(origin)}, so its question is not ${does === "answers" ? "answered" : "retracted"} there either: a person ${does === "answers" ? "answers" : "retracts the answer to"} it at a shell with \`chant workspace points ${does === "answers" ? "answer" : "retract"} ${id}\`, or through hud`,
906
+ );
907
+ }
908
+ }
909
+ }
910
+
838
911
  /**
839
912
  * People answer an open question: `points answer`. A proposed question the
840
913
  * people answer as the model did is confirmed, and keeps the model as its
@@ -884,8 +957,10 @@ async function answerPointLocked(opts: AnswerPointOptions): Promise<PointsWriteD
884
957
  if (value === undefined || !allowed.includes(value)) {
885
958
  throw new PointsWriteError("answer-not-candidate", `${opts.id} takes one of ${allowed.map((c) => JSON.stringify(c)).join(", ")}, not ${JSON.stringify(opts.answer)}`);
886
959
  }
960
+ const origin = opts.origin ?? currentGateOrigin();
961
+ await refuseNeverOverMcp(opts.id, d, o.root, origin, "answers");
887
962
  const quorum = quorumOf(point);
888
- const tally = meetQuorum(name, opts.by, quorum, o.root, askedByOf(d)?.steward, "answer");
963
+ const tally = meetQuorum(name, opts.by, quorum, o.root, askedByOf(d)?.steward, "answer", origin);
889
964
  const on = opts.on ?? today();
890
965
  const decider = d.decider as Record<string, unknown>;
891
966
  const confirmed = target.state === "proposed" && decider.kind === "model" && d.answer === value;
@@ -960,6 +1035,8 @@ export interface RetractAnswerOptions {
960
1035
  kind?: string;
961
1036
  on?: string;
962
1037
  dryRun?: boolean;
1038
+ /** The channel the retraction came through, counted as for an answer (#3817). */
1039
+ origin?: GateOrigin;
963
1040
  }
964
1041
 
965
1042
  /**
@@ -998,8 +1075,10 @@ async function retractAnswerLocked(opts: RetractAnswerOptions): Promise<PointsWr
998
1075
  const name = String(d.point);
999
1076
  const point = pointOf(opened.points, name);
1000
1077
  if (!point) throw new PointsWriteError("point-unknown", `${opts.id} answers ${name}, which ${opened.pointsFile} no longer declares, so no quorum can take the answer back: ask the point as it is declared now`);
1078
+ const origin = opts.origin ?? currentGateOrigin();
1079
+ await refuseNeverOverMcp(opts.id, d, o.root, origin, "retracts");
1001
1080
  const quorum = quorumOf(point);
1002
- const tally = meetQuorum(name, opts.by, quorum, o.root, askedByOf(d)?.steward, "retract");
1081
+ const tally = meetQuorum(name, opts.by, quorum, o.root, askedByOf(d)?.steward, "retract", origin);
1003
1082
  const on = opts.on ?? today();
1004
1083
  const type = String(d.question_type);
1005
1084
  const decider = d.decider !== null && typeof d.decider === "object" && !Array.isArray(d.decider) ? (d.decider as Record<string, unknown>) : { kind: "quorum" };
@@ -626,6 +626,7 @@
626
626
  "answer-not-candidate",
627
627
  "quorum-not-met",
628
628
  "answer-in-steward-turn",
629
+ "answer-never-over-mcp",
629
630
  "principal-unidentified",
630
631
  "answer-not-answered",
631
632
  "answer-field-unsupported",
@@ -157,8 +157,9 @@ export const REASONS = {
157
157
  "point-inputs-invalid": "The inputs given to an ask are not a JSON object of the point's declared inputs.",
158
158
  "point-decider-failed": "A model decider that fails closed (unreachable: fail) could not answer, so the ask wrote nothing.",
159
159
  "answer-not-candidate": "The people's answer is not one of the question's candidates.",
160
- "quorum-not-met": "Too few of the people who answered count toward the point's quorum: distinct, not holding the agent role, not the steward that asked, and holding one of its roles when it names any.",
160
+ "quorum-not-met": "Too few of the people who answered count toward the point's quorum: distinct, not holding the agent role, not the steward that asked, and holding one of its roles when it names any. Nobody named over MCP or ACP counts (#3817).",
161
161
  "answer-in-steward-turn": "The answer was given during a steward's turn, or by a process it started: a steward never answers a decision point, and a person answers it through hud or at a shell.",
162
+ "answer-never-over-mcp": "The answer or retraction came over MCP or ACP, or from a process a session on one started, and the question constrains a gate that is never resolved there: a person answers it at a shell or through hud (#3817).",
162
163
  "answer-not-answered": "points retract names a question that has no answer to retract: it is escalated or proposed, and people answer it instead (#3351).",
163
164
  "answer-field-unsupported": "The answer kind's copy of point-answer.schema.json predates a field the write needs, a note, a relay, a retraction or an ad-hoc question's asked: copy the schema anew to turn it on (#3351, #3402, #3403).",
164
165
  "point-candidates-invalid": "points ask names an ad-hoc point without --candidates, a declared point with them, or candidates that are not a question and criteria of the point's question type (#3403).",