@intentius/chant 0.124.1 → 0.124.3
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.
- package/dist/cli/handlers/override-approve.d.ts +3 -1
- package/dist/cli/handlers/override-approve.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +5 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +2 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/lifecycle/gate-audit.d.ts +37 -13
- package/dist/lifecycle/gate-audit.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +1 -33
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-origin.d.ts +14 -2
- package/dist/lifecycle/gate-origin.d.ts.map +1 -1
- package/dist/lifecycle/gate-pending.d.ts +41 -0
- package/dist/lifecycle/gate-pending.d.ts.map +1 -0
- package/dist/op/activities/activity-contracts.d.ts +1 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/decide.d.ts +2 -0
- package/dist/op/activities/decide.d.ts.map +1 -1
- package/dist/op/gate-point-run.d.ts +5 -77
- package/dist/op/gate-point-run.d.ts.map +1 -1
- package/dist/op/gate-point.d.ts +18 -0
- package/dist/op/gate-point.d.ts.map +1 -1
- package/dist/op/gate.d.ts +8 -0
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/index.d.ts +4 -4
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/op-waves-run.d.ts +37 -6
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves.d.ts +38 -4
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/steward-points.d.ts +7 -0
- package/dist/op/steward-points.d.ts.map +1 -1
- package/dist/override-gate.d.ts +8 -2
- package/dist/override-gate.d.ts.map +1 -1
- package/dist/point-decision.d.ts +134 -0
- package/dist/point-decision.d.ts.map +1 -0
- package/dist/pr-forge.d.ts +37 -2
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/workspace/decide.d.ts +14 -2
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/reason-codes.d.ts +2 -1
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/handlers/override-approve.test.ts +16 -0
- package/src/cli/handlers/override-approve.ts +6 -2
- package/src/cli/main.test.ts +3 -0
- package/src/cli/main.ts +9 -2
- package/src/cli/mcp/workspace-tools.ts +7 -3
- package/src/cli/registry.ts +2 -0
- package/src/lifecycle/gate-audit.test.ts +42 -0
- package/src/lifecycle/gate-audit.ts +102 -34
- package/src/lifecycle/gate-ledger.ts +3 -53
- package/src/lifecycle/gate-origin.ts +20 -3
- package/src/lifecycle/gate-pending.ts +62 -0
- package/src/op/activities/activity-contracts.ts +1 -0
- package/src/op/activities/decide.ts +3 -0
- package/src/op/gate-point-ci.e2e.test.ts +171 -0
- package/src/op/gate-point-mcp.e2e.test.ts +163 -0
- package/src/op/gate-point-run.ts +18 -149
- package/src/op/gate-point.e2e.test.ts +2 -0
- package/src/op/gate-point.test.ts +1 -1
- package/src/op/gate-point.ts +27 -3
- package/src/op/gate.ts +10 -0
- package/src/op/index.ts +10 -1
- package/src/op/op-waves-run.ts +84 -19
- package/src/op/op-waves.test.ts +96 -0
- package/src/op/op-waves.ts +60 -4
- package/src/op/steward-points.ts +8 -0
- package/src/override-gate.test.ts +5 -0
- package/src/override-gate.ts +8 -2
- package/src/point-decision-bundle.test.ts +62 -0
- package/src/point-decision.e2e.test.ts +95 -0
- package/src/point-decision.ts +280 -0
- package/src/pr-forge.test.ts +62 -0
- package/src/pr-forge.ts +60 -9
- package/src/workspace/decide.ts +92 -8
- package/src/workspace/points-cli.ts +1 -1
- package/src/workspace/points-write.schema.json +1 -0
- package/src/workspace/reason-codes.ts +2 -1
|
@@ -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;
|
|
@@ -235,7 +236,9 @@ export interface AskPointOptions {
|
|
|
235
236
|
* or the lifecycle ledger (#2786). Defaults to the ledger in a steward's
|
|
236
237
|
* turn (`steward` given, or this process a steward's turn), since a steward
|
|
237
238
|
* never writes the checkout, and to the tree otherwise. A question already
|
|
238
|
-
* held on the ledger is rewritten there whatever this says.
|
|
239
|
+
* held on the ledger is rewritten there whatever this says. Outside a
|
|
240
|
+
* steward's turn, `points ask --store ledger` and a gate's `point.store`
|
|
241
|
+
* reach it (#3815), for a checkout that does not outlive the run.
|
|
239
242
|
*/
|
|
240
243
|
store?: "tree" | "ledger";
|
|
241
244
|
/** The date written as asked_on, and answered_on for a table's answer, YYYY-MM-DD. Defaults to today, in UTC. */
|
|
@@ -277,6 +280,13 @@ export interface AnswerPointOptions {
|
|
|
277
280
|
kind?: string;
|
|
278
281
|
on?: string;
|
|
279
282
|
dryRun?: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* The channel the answer came through (#3817). Defaults to this process's
|
|
285
|
+
* (`currentGateOrigin`). Over MCP or ACP nobody `by` names counts toward
|
|
286
|
+
* the quorum, and a question that constrains a `neverOverMcp` gate is
|
|
287
|
+
* refused outright.
|
|
288
|
+
*/
|
|
289
|
+
origin?: GateOrigin;
|
|
280
290
|
}
|
|
281
291
|
/**
|
|
282
292
|
* Whether an answer kind's schema copy takes the fields of #3351 (`note` on an
|
|
@@ -328,6 +338,8 @@ export interface RetractAnswerOptions {
|
|
|
328
338
|
kind?: string;
|
|
329
339
|
on?: string;
|
|
330
340
|
dryRun?: boolean;
|
|
341
|
+
/** The channel the retraction came through, counted as for an answer (#3817). */
|
|
342
|
+
origin?: GateOrigin;
|
|
331
343
|
}
|
|
332
344
|
/**
|
|
333
345
|
* 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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAMH,OAAO,EAA4E,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3I,OAAO,EAWL,KAAK,QAAQ,EAEd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAcL,KAAK,KAAK,EAEV,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,KAAK,EACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"decide.d.ts","sourceRoot":"","sources":["../../src/workspace/decide.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAMH,OAAO,EAA4E,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE3I,OAAO,EAWL,KAAK,QAAQ,EAEd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAcL,KAAK,KAAK,EAEV,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,KAAK,EACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOhD,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE/F,mGAAmG;AACnG,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,sBAAsB,0FAA0F,CAAC;AAE9H,8GAA8G;AAC9G,eAAO,MAAM,wBAAwB,i1BAmCK,CAAC;AAC3C,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB;IADrC,YACW,IAAI,EAAE,oBAAoB,EACnC,OAAO,EAAE,MAAM,EAIhB;CACF;AAED,+HAA+H;AAC/H,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IAC7C,4GAA4G;IAC5G,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,wIAAwI;IACxI,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC7C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;OAKG;IACH,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/L,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qGAAqG;IACrG,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,iHAAiH;IACjH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6FAA6F;IAC7F,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B;;;;OAIG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACxD;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,0HAA0H;AAC1H,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+CAA+C;IAC/C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wBAAwB;IACxB,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAsBD,0EAA0E;AAC1E,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAE/C,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAAC,SAAS,CAAC,CAWhF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW,GAAG,YAAY,GAAG,IAAI,CA6D5H;AAED,mCAAmC;AACnC,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3D,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAC3B;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,YAAY,CAAC;IACvB,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACD;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,oBAAoB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAczH;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnF;AAmBD,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kIAAkI;IAClI,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,2FAA2F;IAC3F,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,mDAAmD;IACnD,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;;;OAKG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,iHAAiH;IACjH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAoHD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAInG;AAiBD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAMlF;AA8FD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,iGAAiG;IACjG,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,mHAAmH;IACnH,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,yFAAyF;IACzF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAIzI;AAkBD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EAAE,EACZ,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,EAC3C,MAAM,EAAE,WAAW;AACnB,sFAAsF;AACtF,OAAO,CAAC,EAAE,MAAM,GACf;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CA0B5E;AAsHD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAMxF;AAuGD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,uFAAuF;IACvF,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAM5F"}
|
|
@@ -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
|
@@ -84,4 +84,20 @@ describe("chant approve policy-override", () => {
|
|
|
84
84
|
expect(await runOverrideApprove(ctx({ rules: ["no-drop", "no-lock"], reason: "why", plan: PLAN }))).toBe(0);
|
|
85
85
|
expect(await runOverrideApprove(ctx({ rules: ["no-drop", "no-lock"], reason: "why", plan: DENIAL.planDigest }))).toBe(0);
|
|
86
86
|
});
|
|
87
|
+
|
|
88
|
+
describe("the overriders check (#3824)", () => {
|
|
89
|
+
const args = { rules: ["no-drop", "no-lock"], reason: "why" };
|
|
90
|
+
test("warns when this checkout lists no overriders", async () => {
|
|
91
|
+
vi.stubEnv("CHANT_OVERRIDERS_FROM", "");
|
|
92
|
+
expect(await runOverrideApprove(ctx(args))).toBe(0);
|
|
93
|
+
expect(printed()).toMatch(/has no \.chant\/overriders/);
|
|
94
|
+
});
|
|
95
|
+
test("is skipped when the caller says where it reads its overriders", async () => {
|
|
96
|
+
vi.stubEnv("CHANT_OVERRIDERS_FROM", "policy.override in terragucci.config.ts");
|
|
97
|
+
expect(await runOverrideApprove(ctx(args))).toBe(0);
|
|
98
|
+
expect(printed()).toMatch(/overrides the denial of prod/);
|
|
99
|
+
expect(printed()).not.toMatch(/overriders/);
|
|
100
|
+
vi.unstubAllEnvs();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
87
103
|
});
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
* recorded: the approver says what they are letting through. Whether the
|
|
11
11
|
* override counts is decided by the run, against the overriders and signers
|
|
12
12
|
* at base; this command only warns when the checkout's own overriders file
|
|
13
|
-
* would not count it.
|
|
13
|
+
* would not count it. A product that keeps its overriders in its own config
|
|
14
|
+
* sets `CHANT_OVERRIDERS_FROM` (to where it reads them, e.g. `policy.override
|
|
15
|
+
* in terragucci.config.ts`), and the checkout check is skipped (#3824).
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
import { currentGateOrigin, isModelAuthored } from "../../lifecycle/gate-origin";
|
|
@@ -93,9 +95,11 @@ export async function runOverrideApprove(ctx: CommandContext): Promise<number> {
|
|
|
93
95
|
`This overrides the denial of ${subject} by ${rules.join(", ")} for the plan ${denial.plan || denial.planDigest}. ` +
|
|
94
96
|
`The next run that plans it applies it once; a plan that moves, or rules that change, need their own override.`,
|
|
95
97
|
));
|
|
98
|
+
const from = process.env.CHANT_OVERRIDERS_FROM?.trim();
|
|
99
|
+
if (from) return 0;
|
|
96
100
|
const here = overridersAt(process.cwd(), "HEAD");
|
|
97
101
|
if (!here.active) {
|
|
98
|
-
console.error(formatWarning({ message: `This checkout has no ${OVERRIDERS_PATH}: unless the run reads its overriders from elsewhere at base, no override counts` }));
|
|
102
|
+
console.error(formatWarning({ message: `This checkout has no ${OVERRIDERS_PATH}: unless the run reads its overriders from elsewhere at base, no override counts (a tool that does sets CHANT_OVERRIDERS_FROM to say so)` }));
|
|
99
103
|
} else if (!here.principals.map(norm).includes(norm(outcome.record.resolvedBy))) {
|
|
100
104
|
console.error(formatWarning({ message: `${outcome.record.resolvedBy} is not in ${OVERRIDERS_PATH} here (${here.principals.join(", ") || "nobody"}), so a run that reads it at base does not count this override` }));
|
|
101
105
|
}
|
package/src/cli/main.test.ts
CHANGED
|
@@ -874,6 +874,9 @@ describe("workspace points (ws-058, #2739)", () => {
|
|
|
874
874
|
expect(answer).toMatchObject({ extraPositional: "answer", answer: "medium", bys: ["alice", "bob"] });
|
|
875
875
|
expect(parseArgs(["workspace", "points", "--open", "--json"])).toMatchObject({ open: true, json: true });
|
|
876
876
|
expect(() => parseArgs(["workspace", "points", "ask", "p", "--response", "--json"])).toThrow(/--response needs a JSON file/);
|
|
877
|
+
// #3815: --store ledger holds the question on chant/lifecycle.
|
|
878
|
+
expect(parseArgs(["workspace", "points", "ask", "p", "--inputs", "-", "--store", "ledger"]).store).toBe("ledger");
|
|
879
|
+
expect(() => parseArgs(["workspace", "points", "ask", "p", "--store", "git"])).toThrow(/--store is tree .* or ledger/);
|
|
877
880
|
});
|
|
878
881
|
});
|
|
879
882
|
|
package/src/cli/main.ts
CHANGED
|
@@ -546,6 +546,11 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
546
546
|
// `chant workspace points ask <point> --subject <id>` (#2739): what the question is about.
|
|
547
547
|
result.subject = args[++i];
|
|
548
548
|
if (!result.subject || result.subject.startsWith("-")) throw new Error("--subject needs what the question is about, such as a work item id: --subject <id>");
|
|
549
|
+
} else if (arg === "--store") {
|
|
550
|
+
// `chant workspace points ask <point> --store ledger` (#3815): where a new question goes.
|
|
551
|
+
const store = args[++i];
|
|
552
|
+
if (store !== "tree" && store !== "ledger") throw new Error("--store is tree (the answer kind's directory in the working tree) or ledger (chant/lifecycle): --store <tree|ledger>");
|
|
553
|
+
result.store = store;
|
|
549
554
|
} else if (arg === "--answer") {
|
|
550
555
|
// `chant workspace points answer <id> --answer <value>` (#2739)
|
|
551
556
|
result.answer = args[++i];
|
|
@@ -1212,13 +1217,15 @@ Workspace (level 1, #2524):
|
|
|
1212
1217
|
List the decision points the declared answer kinds'
|
|
1213
1218
|
points files declare, and the questions asked of them;
|
|
1214
1219
|
--open keeps the escalated and proposed ones (ws-058)
|
|
1215
|
-
workspace points ask <point> --inputs <file|-|json> [--candidates <file|-|json>] [--response <file>] [--subject <id>] [--kind <kind file>] [--dry-run]
|
|
1220
|
+
workspace points ask <point> --inputs <file|-|json> [--candidates <file|-|json>] [--response <file>] [--subject <id>] [--store <tree|ledger>] [--kind <kind file>] [--dry-run]
|
|
1216
1221
|
Ask a point's table, model and quorum deciders and
|
|
1217
1222
|
record the answer: proposed from a model, escalated to
|
|
1218
1223
|
people below its threshold. --response is a POST
|
|
1219
1224
|
/v1/systemone response the caller got; chant calls no model.
|
|
1220
1225
|
--candidates gives an ad-hoc point's question and
|
|
1221
|
-
candidates, { question, criteria }
|
|
1226
|
+
candidates, { question, criteria }. --store ledger
|
|
1227
|
+
holds the question on chant/lifecycle and pushes it,
|
|
1228
|
+
for a checkout that does not outlive the run (CI)
|
|
1222
1229
|
workspace points answer <id> --answer <value> --by <name>... [--note <text>] [--relayed-by <principal>] [--kind <kind file>] [--dry-run]
|
|
1223
1230
|
Record people's answer to an open question, or confirm
|
|
1224
1231
|
a model's proposal, once the point's quorum is met,
|
|
@@ -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",
|
package/src/cli/registry.ts
CHANGED
|
@@ -366,6 +366,8 @@ export interface ParsedArgs {
|
|
|
366
366
|
response?: string;
|
|
367
367
|
/** `chant workspace points ask <point> --subject <id>` (#2739): what the question is about. */
|
|
368
368
|
subject?: string;
|
|
369
|
+
/** `chant workspace points ask <point> --store ledger` (#3815): hold the question on chant/lifecycle rather than in the working tree. */
|
|
370
|
+
store?: "tree" | "ledger";
|
|
369
371
|
/** `chant workspace points answer <id> --answer <value>` (#2739): the people's answer. */
|
|
370
372
|
answer?: string;
|
|
371
373
|
/** `chant workspace graph --no-cache` (#2876): read every member, bypassing the per-member cache. */
|
|
@@ -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
|
|
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.
|
|
73
|
-
*
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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").
|
|
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
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
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(
|
|
486
|
+
out.push({ text, commit: commit.trim(), ...(n > 0 ? { added: { ...by } } : { removed: { ...by } }) });
|
|
419
487
|
}
|
|
420
488
|
}
|
|
421
489
|
}
|