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.
- package/dashboard/index.html +73 -11
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +24 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/coordination/MandateAudit.d.ts +48 -0
- package/dist/coordination/MandateAudit.d.ts.map +1 -0
- package/dist/coordination/MandateAudit.js +95 -0
- package/dist/coordination/MandateAudit.js.map +1 -0
- package/dist/coordination/MandateGate.d.ts +48 -0
- package/dist/coordination/MandateGate.d.ts.map +1 -0
- package/dist/coordination/MandateGate.js +104 -0
- package/dist/coordination/MandateGate.js.map +1 -0
- package/dist/coordination/MandateStore.d.ts +60 -0
- package/dist/coordination/MandateStore.d.ts.map +1 -0
- package/dist/coordination/MandateStore.js +106 -0
- package/dist/coordination/MandateStore.js.map +1 -0
- package/dist/coordination/ReviewExchange.d.ts +135 -0
- package/dist/coordination/ReviewExchange.d.ts.map +1 -0
- package/dist/coordination/ReviewExchange.js +192 -0
- package/dist/coordination/ReviewExchange.js.map +1 -0
- package/dist/coordination/conditions.d.ts +32 -0
- package/dist/coordination/conditions.d.ts.map +1 -0
- package/dist/coordination/conditions.js +54 -0
- package/dist/coordination/conditions.js.map +1 -0
- package/dist/coordination/types.d.ts +74 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +17 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/core/ApprovalLedger.d.ts +132 -0
- package/dist/core/ApprovalLedger.d.ts.map +1 -0
- package/dist/core/ApprovalLedger.js +191 -0
- package/dist/core/ApprovalLedger.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +33 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +10 -1
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/SessionBuildContextStore.d.ts +33 -0
- package/dist/core/SessionBuildContextStore.d.ts.map +1 -0
- package/dist/core/SessionBuildContextStore.js +107 -0
- package/dist/core/SessionBuildContextStore.js.map +1 -0
- package/dist/core/SessionManager.d.ts +4 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +44 -3
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/TransferByNickname.d.ts +6 -0
- package/dist/core/TransferByNickname.d.ts.map +1 -1
- package/dist/core/TransferByNickname.js +18 -6
- package/dist/core/TransferByNickname.js.map +1 -1
- package/dist/core/seamlessnessConfig.d.ts.map +1 -1
- package/dist/core/seamlessnessConfig.js +12 -1
- package/dist/core/seamlessnessConfig.js.map +1 -1
- package/dist/core/types.d.ts +34 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/feedback-factory/migration/immutableGuard.d.ts +87 -0
- package/dist/feedback-factory/migration/immutableGuard.d.ts.map +1 -0
- package/dist/feedback-factory/migration/immutableGuard.js +163 -0
- package/dist/feedback-factory/migration/immutableGuard.js.map +1 -0
- package/dist/feedback-factory/migration/importIntegrity.d.ts +112 -0
- package/dist/feedback-factory/migration/importIntegrity.d.ts.map +1 -0
- package/dist/feedback-factory/migration/importIntegrity.js +202 -0
- package/dist/feedback-factory/migration/importIntegrity.js.map +1 -0
- package/dist/feedback-factory/monitor/parityMonitor.d.ts +75 -0
- package/dist/feedback-factory/monitor/parityMonitor.d.ts.map +1 -0
- package/dist/feedback-factory/monitor/parityMonitor.js +98 -0
- package/dist/feedback-factory/monitor/parityMonitor.js.map +1 -0
- package/dist/feedback-factory/monitor/parityMonitorStore.d.ts +44 -0
- package/dist/feedback-factory/monitor/parityMonitorStore.d.ts.map +1 -0
- package/dist/feedback-factory/monitor/parityMonitorStore.js +80 -0
- package/dist/feedback-factory/monitor/parityMonitorStore.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +19 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.d.ts.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.js +1 -0
- package/dist/scheduler/MentorAutonomousGuardian.js.map +1 -1
- package/dist/server/AgentServer.d.ts +11 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +102 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +45 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +19 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +482 -4
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/scaffold/templates.ts +19 -1
- package/upgrades/1.3.270.md +106 -0
- package/upgrades/1.3.271.md +154 -0
- package/upgrades/approval-ledger-phase2.eli16.md +56 -0
- package/upgrades/autoloop-gate-compliance.eli16.md +11 -0
- package/upgrades/feedback-phase3-monitor.eli16.md +51 -0
- package/upgrades/feedback-phase4-integrity.eli16.md +54 -0
- package/upgrades/respawn-build-context-reestablishment.eli16.md +5 -0
- package/upgrades/side-effects/approval-ledger-phase2.md +82 -0
- package/upgrades/side-effects/autoloop-gate-compliance.md +43 -0
- package/upgrades/side-effects/coordination-mandate-enforcement.md +86 -0
- package/upgrades/side-effects/dashboard-pool-sessions.md +103 -0
- package/upgrades/side-effects/feedback-phase3-monitor.md +37 -0
- package/upgrades/side-effects/feedback-phase4-integrity.md +35 -0
- package/upgrades/side-effects/respawn-build-context-reestablishment.md +81 -0
- package/upgrades/side-effects/review-exchange-protocol.md +60 -0
- package/upgrades/side-effects/secret-drop-store-first.md +117 -0
- 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":"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"}
|