instar 1.3.269 → 1.3.271

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dashboard/index.html +73 -11
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +24 -3
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/coordination/MandateAudit.d.ts +48 -0
  6. package/dist/coordination/MandateAudit.d.ts.map +1 -0
  7. package/dist/coordination/MandateAudit.js +95 -0
  8. package/dist/coordination/MandateAudit.js.map +1 -0
  9. package/dist/coordination/MandateGate.d.ts +48 -0
  10. package/dist/coordination/MandateGate.d.ts.map +1 -0
  11. package/dist/coordination/MandateGate.js +104 -0
  12. package/dist/coordination/MandateGate.js.map +1 -0
  13. package/dist/coordination/MandateStore.d.ts +60 -0
  14. package/dist/coordination/MandateStore.d.ts.map +1 -0
  15. package/dist/coordination/MandateStore.js +106 -0
  16. package/dist/coordination/MandateStore.js.map +1 -0
  17. package/dist/coordination/ReviewExchange.d.ts +135 -0
  18. package/dist/coordination/ReviewExchange.d.ts.map +1 -0
  19. package/dist/coordination/ReviewExchange.js +192 -0
  20. package/dist/coordination/ReviewExchange.js.map +1 -0
  21. package/dist/coordination/conditions.d.ts +32 -0
  22. package/dist/coordination/conditions.d.ts.map +1 -0
  23. package/dist/coordination/conditions.js +54 -0
  24. package/dist/coordination/conditions.js.map +1 -0
  25. package/dist/coordination/types.d.ts +74 -0
  26. package/dist/coordination/types.d.ts.map +1 -0
  27. package/dist/coordination/types.js +17 -0
  28. package/dist/coordination/types.js.map +1 -0
  29. package/dist/core/ApprovalLedger.d.ts +132 -0
  30. package/dist/core/ApprovalLedger.d.ts.map +1 -0
  31. package/dist/core/ApprovalLedger.js +191 -0
  32. package/dist/core/ApprovalLedger.js.map +1 -0
  33. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  34. package/dist/core/PostUpdateMigrator.js +33 -1
  35. package/dist/core/PostUpdateMigrator.js.map +1 -1
  36. package/dist/core/SecretStore.d.ts.map +1 -1
  37. package/dist/core/SecretStore.js +10 -1
  38. package/dist/core/SecretStore.js.map +1 -1
  39. package/dist/core/SessionBuildContextStore.d.ts +33 -0
  40. package/dist/core/SessionBuildContextStore.d.ts.map +1 -0
  41. package/dist/core/SessionBuildContextStore.js +107 -0
  42. package/dist/core/SessionBuildContextStore.js.map +1 -0
  43. package/dist/core/SessionManager.d.ts +4 -0
  44. package/dist/core/SessionManager.d.ts.map +1 -1
  45. package/dist/core/SessionManager.js +44 -3
  46. package/dist/core/SessionManager.js.map +1 -1
  47. package/dist/core/TransferByNickname.d.ts +6 -0
  48. package/dist/core/TransferByNickname.d.ts.map +1 -1
  49. package/dist/core/TransferByNickname.js +18 -6
  50. package/dist/core/TransferByNickname.js.map +1 -1
  51. package/dist/core/seamlessnessConfig.d.ts.map +1 -1
  52. package/dist/core/seamlessnessConfig.js +12 -1
  53. package/dist/core/seamlessnessConfig.js.map +1 -1
  54. package/dist/core/types.d.ts +34 -0
  55. package/dist/core/types.d.ts.map +1 -1
  56. package/dist/core/types.js.map +1 -1
  57. package/dist/feedback-factory/migration/immutableGuard.d.ts +87 -0
  58. package/dist/feedback-factory/migration/immutableGuard.d.ts.map +1 -0
  59. package/dist/feedback-factory/migration/immutableGuard.js +163 -0
  60. package/dist/feedback-factory/migration/immutableGuard.js.map +1 -0
  61. package/dist/feedback-factory/migration/importIntegrity.d.ts +112 -0
  62. package/dist/feedback-factory/migration/importIntegrity.d.ts.map +1 -0
  63. package/dist/feedback-factory/migration/importIntegrity.js +202 -0
  64. package/dist/feedback-factory/migration/importIntegrity.js.map +1 -0
  65. package/dist/feedback-factory/monitor/parityMonitor.d.ts +75 -0
  66. package/dist/feedback-factory/monitor/parityMonitor.d.ts.map +1 -0
  67. package/dist/feedback-factory/monitor/parityMonitor.js +98 -0
  68. package/dist/feedback-factory/monitor/parityMonitor.js.map +1 -0
  69. package/dist/feedback-factory/monitor/parityMonitorStore.d.ts +44 -0
  70. package/dist/feedback-factory/monitor/parityMonitorStore.d.ts.map +1 -0
  71. package/dist/feedback-factory/monitor/parityMonitorStore.js +80 -0
  72. package/dist/feedback-factory/monitor/parityMonitorStore.js.map +1 -0
  73. package/dist/scaffold/templates.d.ts.map +1 -1
  74. package/dist/scaffold/templates.js +19 -1
  75. package/dist/scaffold/templates.js.map +1 -1
  76. package/dist/scheduler/MentorAutonomousGuardian.d.ts.map +1 -1
  77. package/dist/scheduler/MentorAutonomousGuardian.js +1 -0
  78. package/dist/scheduler/MentorAutonomousGuardian.js.map +1 -1
  79. package/dist/server/AgentServer.d.ts +11 -0
  80. package/dist/server/AgentServer.d.ts.map +1 -1
  81. package/dist/server/AgentServer.js +102 -1
  82. package/dist/server/AgentServer.js.map +1 -1
  83. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  84. package/dist/server/CapabilityIndex.js +45 -0
  85. package/dist/server/CapabilityIndex.js.map +1 -1
  86. package/dist/server/routes.d.ts +19 -0
  87. package/dist/server/routes.d.ts.map +1 -1
  88. package/dist/server/routes.js +482 -4
  89. package/dist/server/routes.js.map +1 -1
  90. package/package.json +1 -1
  91. package/src/data/builtin-manifest.json +65 -65
  92. package/src/scaffold/templates.ts +19 -1
  93. package/upgrades/1.3.270.md +106 -0
  94. package/upgrades/1.3.271.md +154 -0
  95. package/upgrades/approval-ledger-phase2.eli16.md +56 -0
  96. package/upgrades/autoloop-gate-compliance.eli16.md +11 -0
  97. package/upgrades/feedback-phase3-monitor.eli16.md +51 -0
  98. package/upgrades/feedback-phase4-integrity.eli16.md +54 -0
  99. package/upgrades/respawn-build-context-reestablishment.eli16.md +5 -0
  100. package/upgrades/side-effects/approval-ledger-phase2.md +82 -0
  101. package/upgrades/side-effects/autoloop-gate-compliance.md +43 -0
  102. package/upgrades/side-effects/coordination-mandate-enforcement.md +86 -0
  103. package/upgrades/side-effects/dashboard-pool-sessions.md +103 -0
  104. package/upgrades/side-effects/feedback-phase3-monitor.md +37 -0
  105. package/upgrades/side-effects/feedback-phase4-integrity.md +35 -0
  106. package/upgrades/side-effects/respawn-build-context-reestablishment.md +81 -0
  107. package/upgrades/side-effects/review-exchange-protocol.md +60 -0
  108. package/upgrades/side-effects/secret-drop-store-first.md +117 -0
  109. package/upgrades/side-effects/transfer-idempotency-exactly-once.md +105 -0
@@ -0,0 +1,192 @@
1
+ /**
2
+ * ReviewExchange — the autonomous code-review protocol (spec §7 G2.3).
3
+ *
4
+ * A ReviewExchange is one mutual, mandate-gated sign-off of a review artifact
5
+ * between the two agents named in a Coordination Mandate. It is how Phase-1's
6
+ * "code-owner review" happens WITHOUT the human relaying: the owner agent delivers
7
+ * a review package over Threadline, the peer reviews and returns an authenticated
8
+ * verdict, and BOTH sign-offs are checked against the mandate's `sign-code-review`
9
+ * authority (bounds e.g. `{ artifact: 'migration-port', mutual: true }`) before
10
+ * they are accepted. Every accepted signature carries the audit hash of the gate
11
+ * decision that authorized it — the trail Justin reviews.
12
+ *
13
+ * Asymmetry, stated honestly: the peer's instance may not run this engine yet, so
14
+ * the peer's "signature" is their authenticated Threadline verdict message
15
+ * (Ed25519-authenticated sender → fingerprint), recorded verbatim by reference —
16
+ * kind 'authenticated-peer-verdict'. The local agent's signature goes through the
17
+ * local gate — kind 'mandate-gated-local'. BOTH are gate-evaluated here (named
18
+ * party, bounds, expiry, revocation), so a stranger's verdict or an out-of-bounds
19
+ * artifact is refused identically.
20
+ *
21
+ * State machine (linear, no skips):
22
+ * proposed → delivered → verdict-recorded → complete
23
+ * ↘ changes-requested (terminal: rework = a NEW exchange)
24
+ *
25
+ * The review package is content-addressed: `packageSha256` is fixed at creation
26
+ * and signatures bind to the record that carries it — a different package is a
27
+ * different exchange. Deny-by-default is inherited: with no mandate issued, every
28
+ * sign/verdict path denies.
29
+ */
30
+ import fs from 'node:fs';
31
+ import path from 'node:path';
32
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
33
+ export class ReviewExchangeEngine {
34
+ d;
35
+ constructor(deps) {
36
+ this.d = deps;
37
+ }
38
+ nowIso() {
39
+ return new Date(this.d.now ? this.d.now() : Date.now()).toISOString();
40
+ }
41
+ readAll() {
42
+ try {
43
+ const raw = JSON.parse(fs.readFileSync(this.d.filePath, 'utf8'));
44
+ return Array.isArray(raw) ? raw : [];
45
+ }
46
+ catch { /* @silent-fallback-ok — exchanges file may not exist yet; an empty list is the safe initial state */
47
+ return [];
48
+ }
49
+ }
50
+ writeAll(records) {
51
+ fs.mkdirSync(path.dirname(this.d.filePath), { recursive: true });
52
+ fs.writeFileSync(this.d.filePath, JSON.stringify(records, null, 2));
53
+ }
54
+ save(record) {
55
+ record.updatedAt = this.nowIso();
56
+ const all = this.readAll().filter((r) => r.id !== record.id);
57
+ all.push(record);
58
+ this.writeAll(all);
59
+ return record;
60
+ }
61
+ /** Evaluate `sign-code-review` for one party through the mandate gate. */
62
+ gateSignOff(record, agentFp) {
63
+ return this.d.gate.evaluate({
64
+ action: 'sign-code-review',
65
+ params: { artifact: record.artifact, mutual: true },
66
+ agentFp,
67
+ mandateId: record.mandateId,
68
+ });
69
+ }
70
+ /** Create a new exchange in `proposed`. Validation only — no gate call yet
71
+ * (creating a record delegates nothing; the sign-offs are what the mandate governs). */
72
+ create(input) {
73
+ if (!SHA256_HEX.test(input.packageSha256)) {
74
+ return { ok: false, reason: 'packageSha256 must be a 64-char lowercase sha256 hex digest' };
75
+ }
76
+ if (!input.artifact || !input.packageRef || !input.mandateId) {
77
+ return { ok: false, reason: 'mandateId, artifact, and packageRef are required' };
78
+ }
79
+ if (!Array.isArray(input.parties) || input.parties.length !== 2 || input.parties[0] === input.parties[1]) {
80
+ return { ok: false, reason: 'parties must be two DISTINCT agent fingerprints [ownerFp, peerFp]' };
81
+ }
82
+ const id = input.id ?? (this.d.genId ? this.d.genId() : `rex-${Math.random().toString(36).slice(2, 10)}`);
83
+ if (this.get(id))
84
+ return { ok: false, reason: `exchange "${id}" already exists` };
85
+ const now = this.nowIso();
86
+ const record = {
87
+ id, mandateId: input.mandateId, artifact: input.artifact,
88
+ packageRef: input.packageRef, packageSha256: input.packageSha256,
89
+ parties: input.parties, state: 'proposed',
90
+ deliveredEvidence: null, peerVerdict: null, signatures: [],
91
+ createdAt: now, updatedAt: now,
92
+ };
93
+ return { ok: true, record: this.save(record) };
94
+ }
95
+ /** proposed → delivered. Records the delivery evidence (Threadline message ref). */
96
+ markDelivered(id, evidence) {
97
+ const record = this.get(id);
98
+ if (!record)
99
+ return { ok: false, reason: `exchange "${id}" not found` };
100
+ if (record.state !== 'proposed') {
101
+ return { ok: false, reason: `cannot mark delivered from state "${record.state}" (must be "proposed")` };
102
+ }
103
+ if (!evidence)
104
+ return { ok: false, reason: 'delivery evidence is required' };
105
+ record.state = 'delivered';
106
+ record.deliveredEvidence = evidence;
107
+ return { ok: true, record: this.save(record) };
108
+ }
109
+ /**
110
+ * delivered → verdict-recorded | changes-requested.
111
+ *
112
+ * Records the PEER's authenticated verdict. An 'approve' verdict IS the peer's
113
+ * sign-off, so it is MANDATE-GATED for the peer's fingerprint (named party,
114
+ * bounds, expiry, revocation — a deny refuses the verdict). A 'request-changes'
115
+ * verdict delegates nothing (it is a refusal), so it is recorded ungated — but
116
+ * only from the exchange's named peer.
117
+ */
118
+ recordPeerVerdict(id, input) {
119
+ const record = this.get(id);
120
+ if (!record)
121
+ return { ok: false, reason: `exchange "${id}" not found` };
122
+ if (record.state !== 'delivered') {
123
+ return { ok: false, reason: `cannot record a verdict from state "${record.state}" (must be "delivered")` };
124
+ }
125
+ if (input.peerFp !== record.parties[1]) {
126
+ return { ok: false, reason: `agent ${input.peerFp} is not the named peer reviewer of this exchange` };
127
+ }
128
+ if (!input.evidence || !input.summary) {
129
+ return { ok: false, reason: 'verdict summary and authenticated evidence ref are required' };
130
+ }
131
+ const verdict = {
132
+ verdict: input.verdict, summary: input.summary,
133
+ evidence: input.evidence, recordedAt: this.nowIso(),
134
+ };
135
+ if (input.verdict === 'request-changes') {
136
+ record.state = 'changes-requested';
137
+ record.peerVerdict = verdict;
138
+ return { ok: true, record: this.save(record) };
139
+ }
140
+ // approve = the peer's sign-off → through the mandate gate.
141
+ const decision = this.gateSignOff(record, input.peerFp);
142
+ if (decision.decision === 'deny') {
143
+ return { ok: false, reason: `mandate denied the peer sign-off: ${decision.reason}` };
144
+ }
145
+ record.state = 'verdict-recorded';
146
+ record.peerVerdict = verdict;
147
+ record.signatures.push({
148
+ agentFp: input.peerFp, signedAt: this.nowIso(),
149
+ kind: 'authenticated-peer-verdict', auditHash: decision.audit.hash,
150
+ evidence: input.evidence,
151
+ });
152
+ return { ok: true, record: this.save(record) };
153
+ }
154
+ /**
155
+ * verdict-recorded → complete. The OWNER's countersignature, mandate-gated for
156
+ * the owner's fingerprint. Completion requires the mutual pair: the peer's
157
+ * approve-signature already present + this one.
158
+ */
159
+ sign(id, agentFp) {
160
+ const record = this.get(id);
161
+ if (!record)
162
+ return { ok: false, reason: `exchange "${id}" not found` };
163
+ if (record.state !== 'verdict-recorded') {
164
+ return { ok: false, reason: `cannot sign from state "${record.state}" (must be "verdict-recorded")` };
165
+ }
166
+ if (agentFp !== record.parties[0]) {
167
+ return { ok: false, reason: `agent ${agentFp} is not the named owner of this exchange` };
168
+ }
169
+ if (record.signatures.some((s) => s.agentFp === agentFp)) {
170
+ return { ok: false, reason: 'owner has already signed this exchange' };
171
+ }
172
+ const decision = this.gateSignOff(record, agentFp);
173
+ if (decision.decision === 'deny') {
174
+ return { ok: false, reason: `mandate denied the owner sign-off: ${decision.reason}` };
175
+ }
176
+ record.signatures.push({
177
+ agentFp, signedAt: this.nowIso(),
178
+ kind: 'mandate-gated-local', auditHash: decision.audit.hash,
179
+ evidence: null,
180
+ });
181
+ // Mutual bound satisfied: both named parties have gate-authorized signatures.
182
+ record.state = 'complete';
183
+ return { ok: true, record: this.save(record) };
184
+ }
185
+ get(id) {
186
+ return this.readAll().find((r) => r.id === id);
187
+ }
188
+ list() {
189
+ return this.readAll();
190
+ }
191
+ }
192
+ //# sourceMappingURL=ReviewExchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewExchange.js","sourceRoot":"","sources":["../../src/coordination/ReviewExchange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Conditions registry — named, objective predicates that gate high-risk authorities.
3
+ *
4
+ * Structure > Willpower applied to delegation: a conditioned authority (e.g. a
5
+ * future `execute-cutover`) fires ONLY when its named condition evaluates true from
6
+ * REAL state — `integrity-gate-pass` ← `runIntegrityGate().passed`,
7
+ * `parity-zero-divergence` ← `ParityMonitor.gate().cleared`. The agent's assertion
8
+ * that "it's safe" is NEVER the input; the objective check is (threat-model T7/T10).
9
+ *
10
+ * Resolvers are INJECTED so this module stays decoupled from the integrity/parity
11
+ * machinery. A condition with no wired resolver evaluates **false** (deny-safe): an
12
+ * un-evaluable gate must never fall open. The first mandate (Justin's A/A/B) carries
13
+ * NO conditioned authority, so nothing here is exercised yet — it is built for the
14
+ * future cutover authority and tested on both sides of the boundary.
15
+ */
16
+ /** A resolver returns the live truth of a condition from real state. */
17
+ export type ConditionResolver = () => boolean;
18
+ export declare class ConditionsRegistry {
19
+ private readonly resolvers;
20
+ /** Register (or replace) the resolver for a named condition. */
21
+ register(name: string, resolver: ConditionResolver): this;
22
+ /** True iff the condition is registered. */
23
+ has(name: string): boolean;
24
+ /**
25
+ * Evaluate a (possibly compound) condition. A `+`-joined expression
26
+ * (e.g. 'integrity-gate-pass+parity-zero-divergence') is the AND of its parts —
27
+ * ALL must resolve true. An unregistered part → false (deny-safe). Any resolver
28
+ * that throws → false (deny-safe).
29
+ */
30
+ evaluate(expr: string): boolean;
31
+ }
32
+ //# sourceMappingURL=conditions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditions.d.ts","sourceRoot":"","sources":["../../src/coordination/conditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC;AAE9C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAElE,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKzD,4CAA4C;IAC5C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAYhC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Conditions registry — named, objective predicates that gate high-risk authorities.
3
+ *
4
+ * Structure > Willpower applied to delegation: a conditioned authority (e.g. a
5
+ * future `execute-cutover`) fires ONLY when its named condition evaluates true from
6
+ * REAL state — `integrity-gate-pass` ← `runIntegrityGate().passed`,
7
+ * `parity-zero-divergence` ← `ParityMonitor.gate().cleared`. The agent's assertion
8
+ * that "it's safe" is NEVER the input; the objective check is (threat-model T7/T10).
9
+ *
10
+ * Resolvers are INJECTED so this module stays decoupled from the integrity/parity
11
+ * machinery. A condition with no wired resolver evaluates **false** (deny-safe): an
12
+ * un-evaluable gate must never fall open. The first mandate (Justin's A/A/B) carries
13
+ * NO conditioned authority, so nothing here is exercised yet — it is built for the
14
+ * future cutover authority and tested on both sides of the boundary.
15
+ */
16
+ export class ConditionsRegistry {
17
+ resolvers = new Map();
18
+ /** Register (or replace) the resolver for a named condition. */
19
+ register(name, resolver) {
20
+ this.resolvers.set(name, resolver);
21
+ return this;
22
+ }
23
+ /** True iff the condition is registered. */
24
+ has(name) {
25
+ return this.resolvers.has(name);
26
+ }
27
+ /**
28
+ * Evaluate a (possibly compound) condition. A `+`-joined expression
29
+ * (e.g. 'integrity-gate-pass+parity-zero-divergence') is the AND of its parts —
30
+ * ALL must resolve true. An unregistered part → false (deny-safe). Any resolver
31
+ * that throws → false (deny-safe).
32
+ */
33
+ evaluate(expr) {
34
+ const parts = expr.split('+').map((p) => p.trim()).filter(Boolean);
35
+ if (parts.length === 0)
36
+ return false;
37
+ for (const part of parts) {
38
+ const resolver = this.resolvers.get(part);
39
+ if (!resolver)
40
+ return false;
41
+ let result;
42
+ try {
43
+ result = resolver() === true;
44
+ }
45
+ catch {
46
+ result = false;
47
+ }
48
+ if (!result)
49
+ return false;
50
+ }
51
+ return true;
52
+ }
53
+ }
54
+ //# sourceMappingURL=conditions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditions.js","sourceRoot":"","sources":["../../src/coordination/conditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,OAAO,kBAAkB;IACZ,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IAElE,gEAAgE;IAChE,QAAQ,CAAC,IAAY,EAAE,QAA2B;QAChD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IAC5C,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,IAAY;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5B,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBAAC,MAAM,GAAG,QAAQ,EAAE,KAAK,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,MAAM,GAAG,KAAK,CAAC;YAAC,CAAC;YAC/D,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Coordination Mandate — shared types.
3
+ *
4
+ * A Coordination Mandate is a human-authored, signed, bounded, conditioned,
5
+ * revocable, audited delegation of SPECIFIC authorities to a SPECIFIC pair of
6
+ * agents for a SPECIFIC purpose and bounded time. It moves the human's
7
+ * authorization from per-action to standing-policy WITHOUT removing the human as
8
+ * the authorizer — preserving `requester ≠ authorizer` (the agent is the
9
+ * requester; the human-authored mandate is the authorizer).
10
+ *
11
+ * Spec: docs/specs/coordination-mandate.md (§4 concrete shape). The first mandate's
12
+ * resolved bounds (Justin's A/A/B sign-off, 2026-06-05): cutover stays his manual
13
+ * click; issuance is dashboard-PIN-gated; the first mandate carries only authorities
14
+ * 1–2 (exchange-read-credential + sign-code-review), NOT execute-cutover.
15
+ */
16
+ /** A single delegated authority within a mandate. */
17
+ export interface Authority {
18
+ /** The action this authority permits, e.g. 'exchange-read-credential' | 'sign-code-review' | 'execute-cutover'. */
19
+ action: string;
20
+ /** Explicit bounds the action's params must satisfy (exact-match per key). */
21
+ bounds: Record<string, unknown>;
22
+ /** Optional objective gate that must evaluate true before the action is allowed,
23
+ * e.g. 'integrity-gate-pass' | 'parity-zero-divergence'. Resolved from REAL state,
24
+ * never from an agent's assertion. */
25
+ requiresCondition?: string;
26
+ }
27
+ /** The human-authored delegation. `authProof` covers all other fields. */
28
+ export interface CoordinationMandate {
29
+ id: string;
30
+ /** e.g. 'feedback-migration'. */
31
+ scope: string;
32
+ /** The two agents bound by the mandate, by routing fingerprint. */
33
+ agents: [string, string];
34
+ authorities: Authority[];
35
+ /** Always the human author identifier (e.g. 'justin'). */
36
+ author: string;
37
+ createdAt: string;
38
+ expiresAt: string;
39
+ /** Set when revoked; checked on every action. */
40
+ revoked: {
41
+ at: string;
42
+ reason: string;
43
+ } | null;
44
+ /** Authorship proof — an HMAC over the canonical (proof-excluded) mandate bytes,
45
+ * produced ONLY by the PIN-gated issuance path. An agent cannot mint or widen its
46
+ * own mandate without it; a forged/edited mandate fails verification. */
47
+ authProof: string;
48
+ }
49
+ export type MandateDecision = 'allow' | 'deny';
50
+ /** The input to a gate evaluation — what the agent is asking to do. */
51
+ export interface MandateEvaluation {
52
+ action: string;
53
+ params: Record<string, unknown>;
54
+ /** The calling agent's routing fingerprint (must be a named party). */
55
+ agentFp: string;
56
+ mandateId: string;
57
+ }
58
+ /** A single audited gate decision (one row of the hash-chained audit). */
59
+ export interface MandateAuditEntry {
60
+ ts: string;
61
+ mandateId: string;
62
+ agentFp: string;
63
+ action: string;
64
+ decision: MandateDecision;
65
+ /** Human-readable reason — which check passed/failed. */
66
+ reason: string;
67
+ /** The condition result when a `requiresCondition` was evaluated (else null). */
68
+ conditionResult: boolean | null;
69
+ /** Hash of the previous entry (genesis = ''), making the log tamper-evident (T8). */
70
+ prevHash: string;
71
+ /** sha256(prevHash + canonical(this-entry-without-hash)). */
72
+ hash: string;
73
+ }
74
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coordination/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,mHAAmH;IACnH,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;2CAEuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/C;;8EAE0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAE/C,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,CAAC;IAC1B,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Coordination Mandate — shared types.
3
+ *
4
+ * A Coordination Mandate is a human-authored, signed, bounded, conditioned,
5
+ * revocable, audited delegation of SPECIFIC authorities to a SPECIFIC pair of
6
+ * agents for a SPECIFIC purpose and bounded time. It moves the human's
7
+ * authorization from per-action to standing-policy WITHOUT removing the human as
8
+ * the authorizer — preserving `requester ≠ authorizer` (the agent is the
9
+ * requester; the human-authored mandate is the authorizer).
10
+ *
11
+ * Spec: docs/specs/coordination-mandate.md (§4 concrete shape). The first mandate's
12
+ * resolved bounds (Justin's A/A/B sign-off, 2026-06-05): cutover stays his manual
13
+ * click; issuance is dashboard-PIN-gated; the first mandate carries only authorities
14
+ * 1–2 (exchange-read-credential + sign-code-review), NOT execute-cutover.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/coordination/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * ApprovalLedger — the durable, signed, append-only record of every operator
3
+ * approval decision, and the per-class agreement ratios computed from it.
4
+ *
5
+ * This is Phase 2 of the approved "Approval-as-Data" spec
6
+ * (`docs/specs/AUTONOMOUS-OPERATION-JUDGMENT-AND-APPROVAL-AS-DATA-SPEC.md`, Part B):
7
+ * an approval stops being a one-shot "approved" with no memory and becomes data —
8
+ * recorded as `approved-as-is` vs `approved-with-change` vs `rejected`, with the
9
+ * WHY of each divergence, so we can (a) see per decision-class where the operator
10
+ * agrees with the agent's recommendation as-is vs revises it, (b) trend toward
11
+ * approved-as-is by folding recurring divergences back into design guidance, and
12
+ * (c) — once a class's ratio holds — pilot auto-approval for that class (Phase 3).
13
+ *
14
+ * SCOPE (operator extension, 2026-06-05): the original spec tracked only official
15
+ * SPEC sign-offs. Justin extended it to track ALL approvals wherever they occur —
16
+ * a spec sign-off, a decision presented and approved in chat, or any other surface.
17
+ * Hence `subject`/`decisionClass`/`surface` (general) rather than `specSlug`/
18
+ * `specClass`, and the spec-only fields (`reviewIterations`/`commitSha`/`evidenceRef`)
19
+ * are optional — a chat approval simply omits them.
20
+ *
21
+ * Mirrors `SessionPoolE2EResultStore` exactly (signed, append-only, tamper-evident,
22
+ * torn-line-tolerant). The store is signer-agnostic — `sign`/`verifySig` are injected
23
+ * — so tests use an Ed25519 keypair and production uses an HMAC over the state secret.
24
+ *
25
+ * AUTHORITY INVARIANT (spec B1, load-bearing for correctness — NOT just integrity):
26
+ * for a MANUAL decision the OPERATOR is the authoritative source of `mode` and
27
+ * `divergences`. The agent must NEVER self-classify the operator's intent. The
28
+ * writer passes the operator-sourced classification (from the approve control / an
29
+ * explicit "as-is" vs "with changes: …"); this store records it faithfully. HMAC/
30
+ * signature guarantees integrity, not correctness — the authoritative-source rule
31
+ * is what prevents an agent inflating its own agreement ratio. An operator can
32
+ * dispute and CORRECT any row: a correction is itself an appended, signed row
33
+ * (`corrects` set), never an in-place edit — history preserved.
34
+ */
35
+ export type ApprovalMode = 'approved-as-is' | 'approved-with-change' | 'rejected';
36
+ /** Where the approval happened (operator-extension axis — "wherever they occur"). */
37
+ export type ApprovalSurface = 'spec' | 'chat' | 'other';
38
+ export declare const APPROVAL_SURFACES: readonly ApprovalSurface[];
39
+ /** Divergence taxonomy (spec B2). `missing-principle` is a candidate trigger to
40
+ * propose a new design principle — a PROPOSAL only, never auto-merged (Part C). */
41
+ export type DivergenceCategory = 'missing-principle' | 'risk-reduction' | 'scope-correction' | 'efficiency' | 'new-information' | 'style';
42
+ export declare const DIVERGENCE_CATEGORIES: readonly DivergenceCategory[];
43
+ export interface Divergence {
44
+ category: DivergenceCategory;
45
+ /** One-line what-changed. */
46
+ summary: string;
47
+ /** Why the operator changed it — the signal we fold back into design guidance. */
48
+ why: string;
49
+ }
50
+ export interface ApprovalRecord {
51
+ /** What was approved — a spec slug, or a stable id for a chat recommendation. */
52
+ subject: string;
53
+ /** The bucket the ratio is computed per (e.g. 'governance-safety', 'design-decision'). */
54
+ decisionClass: string;
55
+ /** Where the approval occurred. */
56
+ surface: ApprovalSurface;
57
+ decidedAt: string;
58
+ /** 'justin' for a manual decision; 'auto' for an auto-approval (Phase 3). */
59
+ approver: string;
60
+ mode: ApprovalMode;
61
+ /** Empty when approved-as-is; one entry per operator-stated change otherwise. */
62
+ divergences: Divergence[];
63
+ /** Spec-context fields — optional (a chat approval omits them). */
64
+ reviewIterations?: number;
65
+ commitSha?: string;
66
+ evidenceRef?: string;
67
+ /** Set when this row CORRECTS a prior row (operator dispute) — the prior subject+decidedAt. */
68
+ corrects?: string;
69
+ signature: string;
70
+ }
71
+ export type ApprovalRecordInput = Omit<ApprovalRecord, 'signature' | 'decidedAt' | 'divergences'> & {
72
+ decidedAt?: string;
73
+ divergences?: Divergence[];
74
+ };
75
+ export interface ApprovalLedgerDeps {
76
+ /** Absolute path to the append-only ledger file. */
77
+ filePath: string;
78
+ /** Sign the canonical (signature-excluded) row. Production: HMAC over the state secret. */
79
+ sign: (canonical: string) => string;
80
+ /** Verify a signature against the canonical row. */
81
+ verifySig: (canonical: string, signature: string) => boolean;
82
+ now?: () => number;
83
+ }
84
+ /** Eligibility knobs for `autoApprovalEligible` (a read-only SIGNAL; never gates here). */
85
+ export interface EligibilityPolicy {
86
+ /** Minimum approved-as-is ratio for a class to be auto-approval-eligible. */
87
+ minRatio: number;
88
+ /** Minimum CURRENT consecutive approved-as-is streak. */
89
+ minStreak: number;
90
+ /** Minimum total decisions in the class (don't qualify on a tiny sample). */
91
+ minTotal: number;
92
+ }
93
+ export declare const DEFAULT_ELIGIBILITY: EligibilityPolicy;
94
+ export interface ClassSummary {
95
+ decisionClass: string;
96
+ total: number;
97
+ approvedAsIs: number;
98
+ approvedWithChange: number;
99
+ rejected: number;
100
+ /** approvedAsIs / total (0 when total is 0). */
101
+ ratio: number;
102
+ /** CURRENT consecutive approved-as-is run (most recent rows), reset to 0 by any
103
+ * approved-with-change or rejected (spec B3). */
104
+ streak: number;
105
+ autoApprovalEligible: boolean;
106
+ /** Aggregate divergence-category counts for the class (drives the Phase-3 digest). */
107
+ divergenceCounts: Record<DivergenceCategory, number>;
108
+ }
109
+ /** Canonical bytes a row's signature covers — field-ordered, signature EXCLUDED.
110
+ * Optional fields are normalized so a present-vs-absent field is unambiguous, and
111
+ * divergences are flattened deterministically so reordering is detectable. */
112
+ export declare function canonicalApprovalRow(r: Omit<ApprovalRecord, 'signature'>): string;
113
+ export declare class ApprovalLedger {
114
+ private readonly d;
115
+ constructor(deps: ApprovalLedgerDeps);
116
+ /**
117
+ * Append a signed approval row. The `mode` + `divergences` MUST be operator-sourced
118
+ * (the authority invariant above) — this method does not infer them.
119
+ * Throws on an internally-inconsistent row so a malformed record can't pollute ratios.
120
+ */
121
+ recordApproval(input: ApprovalRecordInput): ApprovalRecord;
122
+ /** All rows (oldest→newest). Tolerant of a missing file / a torn trailing line. */
123
+ all(): ApprovalRecord[];
124
+ /** Verify a row's signature (tamper check). */
125
+ verify(row: ApprovalRecord): boolean;
126
+ /** Per-class agreement summary. Read-only; never gates by itself (spec B3). */
127
+ summarize(policy?: EligibilityPolicy): ClassSummary[];
128
+ /** Summary for one class (returns a zeroed summary if the class has no rows). */
129
+ summaryForClass(decisionClass: string, policy?: EligibilityPolicy): ClassSummary;
130
+ private summarizeRows;
131
+ }
132
+ //# sourceMappingURL=ApprovalLedger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApprovalLedger.d.ts","sourceRoot":"","sources":["../../src/core/ApprovalLedger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,UAAU,CAAC;AAElF,qFAAqF;AACrF,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAAuC,CAAC;AAEhG;oFACoF;AACpF,MAAM,MAAM,kBAAkB,GAC1B,mBAAmB,GACnB,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,iBAAiB,GACjB,OAAO,CAAC;AAEZ,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAGrD,CAAC;AAEX,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,iFAAiF;IACjF,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,mBAAmB,GAC7B,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,WAAW,GAAG,aAAa,CAAC,GAC7D;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,oDAAoD;IACpD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,mBAAmB,EAAE,iBAAgE,CAAC;AAEnG,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd;sDACkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,OAAO,CAAC;IAC9B,sFAAsF;IACtF,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;CACtD;AAED;;+EAE+E;AAC/E,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,GAAG,MAAM,CAcjF;AASD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAqB;gBAC3B,IAAI,EAAE,kBAAkB;IAIpC;;;;OAIG;IACH,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc;IA4C1D,mFAAmF;IACnF,GAAG,IAAI,cAAc,EAAE;IAWvB,+CAA+C;IAC/C,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO;IAKpC,+EAA+E;IAC/E,SAAS,CAAC,MAAM,GAAE,iBAAuC,GAAG,YAAY,EAAE;IAgB1E,iFAAiF;IACjF,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,GAAE,iBAAuC,GAAG,YAAY;IAKrG,OAAO,CAAC,aAAa;CAwBtB"}