@guyghost/swarm-dao-core 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/attention/fs-attention.store.d.ts +17 -0
- package/dist/adapters/attention/fs-attention.store.d.ts.map +1 -0
- package/dist/adapters/attention/fs-attention.store.js +59 -0
- package/dist/adapters/attention/fs-attention.store.js.map +1 -0
- package/dist/adapters/git-workspace.d.ts +26 -0
- package/dist/adapters/git-workspace.d.ts.map +1 -0
- package/dist/adapters/git-workspace.js +84 -0
- package/dist/adapters/git-workspace.js.map +1 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +7 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/persistence/file-dao-state.repository.d.ts +15 -0
- package/dist/adapters/persistence/file-dao-state.repository.d.ts.map +1 -0
- package/dist/adapters/persistence/file-dao-state.repository.js +85 -0
- package/dist/adapters/persistence/file-dao-state.repository.js.map +1 -0
- package/dist/adapters/persistence/in-memory-dao-state.repository.d.ts +10 -0
- package/dist/adapters/persistence/in-memory-dao-state.repository.d.ts.map +1 -0
- package/dist/adapters/persistence/in-memory-dao-state.repository.js +14 -0
- package/dist/adapters/persistence/in-memory-dao-state.repository.js.map +1 -0
- package/dist/adapters/persistence/legacy-dao-state.repository.d.ts +11 -0
- package/dist/adapters/persistence/legacy-dao-state.repository.d.ts.map +1 -0
- package/dist/adapters/persistence/legacy-dao-state.repository.js +14 -0
- package/dist/adapters/persistence/legacy-dao-state.repository.js.map +1 -0
- package/dist/adapters/ship-audit/fs-ship-audit.store.d.ts +12 -0
- package/dist/adapters/ship-audit/fs-ship-audit.store.d.ts.map +1 -0
- package/dist/adapters/ship-audit/fs-ship-audit.store.js +69 -0
- package/dist/adapters/ship-audit/fs-ship-audit.store.js.map +1 -0
- package/dist/application/index.d.ts +16 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +16 -0
- package/dist/application/index.js.map +1 -0
- package/dist/application/initialize-dao.use-case.d.ts +20 -0
- package/dist/application/initialize-dao.use-case.d.ts.map +1 -0
- package/dist/application/initialize-dao.use-case.js +17 -0
- package/dist/application/initialize-dao.use-case.js.map +1 -0
- package/dist/application/proposals/control-proposal.use-case.d.ts +23 -0
- package/dist/application/proposals/control-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/control-proposal.use-case.js +53 -0
- package/dist/application/proposals/control-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/create-amendment-proposal.use-case.d.ts +25 -0
- package/dist/application/proposals/create-amendment-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/create-amendment-proposal.use-case.js +39 -0
- package/dist/application/proposals/create-amendment-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/create-proposal.use-case.d.ts +34 -0
- package/dist/application/proposals/create-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/create-proposal.use-case.js +49 -0
- package/dist/application/proposals/create-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/deliberate-proposal.use-case.d.ts +35 -0
- package/dist/application/proposals/deliberate-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/deliberate-proposal.use-case.js +67 -0
- package/dist/application/proposals/deliberate-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/dry-run-proposal.use-case.d.ts +21 -0
- package/dist/application/proposals/dry-run-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/dry-run-proposal.use-case.js +20 -0
- package/dist/application/proposals/dry-run-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/execute-proposal.use-case.d.ts +29 -0
- package/dist/application/proposals/execute-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/execute-proposal.use-case.js +66 -0
- package/dist/application/proposals/execute-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/rate-proposal.use-case.d.ts +24 -0
- package/dist/application/proposals/rate-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/rate-proposal.use-case.js +33 -0
- package/dist/application/proposals/rate-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/record-deliberation-outputs.use-case.d.ts +21 -0
- package/dist/application/proposals/record-deliberation-outputs.use-case.d.ts.map +1 -0
- package/dist/application/proposals/record-deliberation-outputs.use-case.js +65 -0
- package/dist/application/proposals/record-deliberation-outputs.use-case.js.map +1 -0
- package/dist/application/proposals/rollback-proposal.use-case.d.ts +20 -0
- package/dist/application/proposals/rollback-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/rollback-proposal.use-case.js +17 -0
- package/dist/application/proposals/rollback-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/round-table.use-case.d.ts +27 -0
- package/dist/application/proposals/round-table.use-case.d.ts.map +1 -0
- package/dist/application/proposals/round-table.use-case.js +55 -0
- package/dist/application/proposals/round-table.use-case.js.map +1 -0
- package/dist/application/proposals/ship-proposal.use-case.d.ts +26 -0
- package/dist/application/proposals/ship-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/ship-proposal.use-case.js +60 -0
- package/dist/application/proposals/ship-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/start-deliberation.use-case.d.ts +21 -0
- package/dist/application/proposals/start-deliberation.use-case.d.ts.map +1 -0
- package/dist/application/proposals/start-deliberation.use-case.js +30 -0
- package/dist/application/proposals/start-deliberation.use-case.js.map +1 -0
- package/dist/application/proposals/transition-proposal.use-case.d.ts +20 -0
- package/dist/application/proposals/transition-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/transition-proposal.use-case.js +19 -0
- package/dist/application/proposals/transition-proposal.use-case.js.map +1 -0
- package/dist/application/proposals/update-proposal.use-case.d.ts +26 -0
- package/dist/application/proposals/update-proposal.use-case.d.ts.map +1 -0
- package/dist/application/proposals/update-proposal.use-case.js +19 -0
- package/dist/application/proposals/update-proposal.use-case.js.map +1 -0
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +18 -3
- package/dist/commands/registry.js.map +1 -1
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/control/gates.d.ts +4 -1
- package/dist/control/gates.d.ts.map +1 -1
- package/dist/control/gates.js +5 -10
- package/dist/control/gates.js.map +1 -1
- package/dist/delivery/dry-run.d.ts.map +1 -1
- package/dist/delivery/dry-run.js +3 -44
- package/dist/delivery/dry-run.js.map +1 -1
- package/dist/delivery/execution-isolation.d.ts +34 -0
- package/dist/delivery/execution-isolation.d.ts.map +1 -0
- package/dist/delivery/execution-isolation.js +97 -0
- package/dist/delivery/execution-isolation.js.map +1 -0
- package/dist/delivery/index.d.ts +2 -0
- package/dist/delivery/index.d.ts.map +1 -1
- package/dist/delivery/index.js +2 -0
- package/dist/delivery/index.js.map +1 -1
- package/dist/delivery/plans.d.ts +3 -1
- package/dist/delivery/plans.d.ts.map +1 -1
- package/dist/delivery/plans.js +2 -2
- package/dist/delivery/plans.js.map +1 -1
- package/dist/delivery/ship-audit.d.ts +36 -0
- package/dist/delivery/ship-audit.d.ts.map +1 -0
- package/dist/delivery/ship-audit.js +155 -0
- package/dist/delivery/ship-audit.js.map +1 -0
- package/dist/domain/dry-run.d.ts +3 -0
- package/dist/domain/dry-run.d.ts.map +1 -0
- package/dist/domain/dry-run.js +28 -0
- package/dist/domain/dry-run.js.map +1 -0
- package/dist/domain/index.d.ts +6 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +7 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/governance/agents.d.ts.map +1 -1
- package/dist/governance/agents.js +107 -169
- package/dist/governance/agents.js.map +1 -1
- package/dist/governance/charter.d.ts +14 -0
- package/dist/governance/charter.d.ts.map +1 -0
- package/dist/governance/charter.js +65 -0
- package/dist/governance/charter.js.map +1 -0
- package/dist/governance/edit-gate.d.ts +47 -0
- package/dist/governance/edit-gate.d.ts.map +1 -0
- package/dist/governance/edit-gate.js +156 -0
- package/dist/governance/edit-gate.js.map +1 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.d.ts.map +1 -1
- package/dist/governance/index.js +1 -0
- package/dist/governance/index.js.map +1 -1
- package/dist/governance/proposal.machine.d.ts +2 -114
- package/dist/governance/proposal.machine.d.ts.map +1 -1
- package/dist/governance/proposal.machine.js +2 -180
- package/dist/governance/proposal.machine.js.map +1 -1
- package/dist/governance/proposal.utils.d.ts +5 -2
- package/dist/governance/proposal.utils.d.ts.map +1 -1
- package/dist/governance/proposal.utils.js +7 -4
- package/dist/governance/proposal.utils.js.map +1 -1
- package/dist/governance/voting.d.ts.map +1 -1
- package/dist/governance/voting.js +24 -14
- package/dist/governance/voting.js.map +1 -1
- package/dist/host-tools/github-config.d.ts.map +1 -1
- package/dist/host-tools/github-config.js +17 -5
- package/dist/host-tools/github-config.js.map +1 -1
- package/dist/host-tools/handlers.d.ts +14 -11
- package/dist/host-tools/handlers.d.ts.map +1 -1
- package/dist/host-tools/handlers.js +247 -341
- package/dist/host-tools/handlers.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/github.d.ts.map +1 -1
- package/dist/integrations/github.js +5 -2
- package/dist/integrations/github.js.map +1 -1
- package/dist/intelligence/delegation.d.ts +3 -2
- package/dist/intelligence/delegation.d.ts.map +1 -1
- package/dist/intelligence/delegation.js.map +1 -1
- package/dist/intelligence/index.d.ts +1 -0
- package/dist/intelligence/index.d.ts.map +1 -1
- package/dist/intelligence/index.js +1 -0
- package/dist/intelligence/index.js.map +1 -1
- package/dist/intelligence/roundtable.d.ts +4 -2
- package/dist/intelligence/roundtable.d.ts.map +1 -1
- package/dist/intelligence/roundtable.js +2 -2
- package/dist/intelligence/roundtable.js.map +1 -1
- package/dist/intelligence/sequential.d.ts +36 -0
- package/dist/intelligence/sequential.d.ts.map +1 -0
- package/dist/intelligence/sequential.js +91 -0
- package/dist/intelligence/sequential.js.map +1 -0
- package/dist/intelligence/swarm.d.ts +8 -4
- package/dist/intelligence/swarm.d.ts.map +1 -1
- package/dist/intelligence/swarm.js +10 -3
- package/dist/intelligence/swarm.js.map +1 -1
- package/dist/intelligence/synthesis.d.ts.map +1 -1
- package/dist/intelligence/synthesis.js +16 -4
- package/dist/intelligence/synthesis.js.map +1 -1
- package/dist/models/graph-engineering.machine.d.ts +219 -0
- package/dist/models/graph-engineering.machine.d.ts.map +1 -0
- package/dist/models/graph-engineering.machine.js +214 -0
- package/dist/models/graph-engineering.machine.js.map +1 -0
- package/dist/models/improvement-loop.machine.d.ts +239 -0
- package/dist/models/improvement-loop.machine.d.ts.map +1 -0
- package/dist/models/improvement-loop.machine.js +254 -0
- package/dist/models/improvement-loop.machine.js.map +1 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +6 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/product-loop.machine.d.ts +531 -0
- package/dist/models/product-loop.machine.d.ts.map +1 -0
- package/dist/models/product-loop.machine.js +699 -0
- package/dist/models/product-loop.machine.js.map +1 -0
- package/dist/models/proposal.machine.d.ts +82 -0
- package/dist/models/proposal.machine.d.ts.map +1 -0
- package/dist/models/proposal.machine.js +68 -0
- package/dist/models/proposal.machine.js.map +1 -0
- package/dist/models/ship-audit.machine.d.ts +103 -0
- package/dist/models/ship-audit.machine.d.ts.map +1 -0
- package/dist/models/ship-audit.machine.js +113 -0
- package/dist/models/ship-audit.machine.js.map +1 -0
- package/dist/observability/attention.d.ts +40 -0
- package/dist/observability/attention.d.ts.map +1 -0
- package/dist/observability/attention.js +119 -0
- package/dist/observability/attention.js.map +1 -0
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +1 -0
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/logging.d.ts +6 -0
- package/dist/observability/logging.d.ts.map +1 -1
- package/dist/observability/logging.js +36 -6
- package/dist/observability/logging.js.map +1 -1
- package/dist/observability/metrics.d.ts +7 -0
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +179 -43
- package/dist/observability/metrics.js.map +1 -1
- package/dist/persistence.d.ts +3 -0
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js +88 -17
- package/dist/persistence.js.map +1 -1
- package/dist/ports/clock.d.ts +7 -0
- package/dist/ports/clock.d.ts.map +1 -0
- package/dist/ports/clock.js +5 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/host.d.ts +8 -0
- package/dist/ports/host.d.ts.map +1 -0
- package/dist/ports/host.js +2 -0
- package/dist/ports/host.js.map +1 -0
- package/dist/ports/index.d.ts +6 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +6 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/repository.d.ts +7 -0
- package/dist/ports/repository.d.ts.map +1 -0
- package/dist/ports/repository.js +2 -0
- package/dist/ports/repository.js.map +1 -0
- package/dist/ports/ship-audit.d.ts +26 -0
- package/dist/ports/ship-audit.d.ts.map +1 -0
- package/dist/ports/ship-audit.js +9 -0
- package/dist/ports/ship-audit.js.map +1 -0
- package/dist/ports/workspace.d.ts +14 -0
- package/dist/ports/workspace.d.ts.map +1 -0
- package/dist/ports/workspace.js +14 -0
- package/dist/ports/workspace.js.map +1 -0
- package/dist/presenters/index.d.ts +2 -0
- package/dist/presenters/index.d.ts.map +1 -0
- package/dist/presenters/index.js +2 -0
- package/dist/presenters/index.js.map +1 -0
- package/dist/presenters/proposal.presenter.d.ts +30 -0
- package/dist/presenters/proposal.presenter.d.ts.map +1 -0
- package/dist/presenters/proposal.presenter.js +47 -0
- package/dist/presenters/proposal.presenter.js.map +1 -0
- package/dist/utils/host.d.ts.map +1 -1
- package/dist/utils/host.js +77 -6
- package/dist/utils/host.js.map +1 -1
- package/dist/utils/security.d.ts +7 -1
- package/dist/utils/security.d.ts.map +1 -1
- package/dist/utils/security.js +18 -2
- package/dist/utils/security.js.map +1 -1
- package/package.json +13 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Swarm DAO Core — Ship Audit Delivery (fingerprint + gate)
|
|
3
|
+
// ============================================================
|
|
4
|
+
// Deterministic glue between the ship handler and the audit machine:
|
|
5
|
+
// - computeShipFingerprint: canonical sha256 over the proposal's
|
|
6
|
+
// decision-relevant content (anything that changes the decision must
|
|
7
|
+
// re-challenge — INV-2). Uses node:crypto; lives OUTSIDE src/models to
|
|
8
|
+
// respect the models purity contract.
|
|
9
|
+
// - evaluateShipAuditChallenge: the gate the handler consults before
|
|
10
|
+
// ShipProposalUseCase. Never mutates proposal state. The challenge binds
|
|
11
|
+
// the decision fingerprint AND the ship options (cascade): changing the
|
|
12
|
+
// operation between challenge and confirmation re-issues the challenge.
|
|
13
|
+
// The read→transition→write sequence runs under an exclusive cross-process
|
|
14
|
+
// claim, so one confirmation can never authorize concurrent ships (INV-6).
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
import { computeShipAuditDecision, createShipAuditActor, } from "../models/ship-audit.machine.js";
|
|
17
|
+
/** Canonical decision-relevant content of a proposal. Pure data selection. */
|
|
18
|
+
function decisionContent(proposal) {
|
|
19
|
+
const control = proposal.riskZone ? { riskZone: proposal.riskZone } : {};
|
|
20
|
+
return {
|
|
21
|
+
id: proposal.id,
|
|
22
|
+
title: proposal.title,
|
|
23
|
+
type: proposal.type,
|
|
24
|
+
description: proposal.description,
|
|
25
|
+
status: proposal.status,
|
|
26
|
+
dependsOn: proposal.dependsOn ?? [],
|
|
27
|
+
votes: (proposal.votes ?? []).map((vote) => ({
|
|
28
|
+
agentId: vote.agentId,
|
|
29
|
+
position: vote.position,
|
|
30
|
+
weight: vote.weight,
|
|
31
|
+
})),
|
|
32
|
+
control,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** sha256 over canonical JSON of the decision content. Deterministic. */
|
|
36
|
+
export function computeShipFingerprint(proposal) {
|
|
37
|
+
const canonical = JSON.stringify(decisionContent(proposal), null, 0);
|
|
38
|
+
return createHash("sha256").update(canonical).digest("hex");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The challenge binds the decision fingerprint plus the operation options:
|
|
42
|
+
* a single-proposal command must not morph into a cascading execution (or
|
|
43
|
+
* the reverse) under one confirmation.
|
|
44
|
+
*/
|
|
45
|
+
function requestSignature(fingerprint, options) {
|
|
46
|
+
return createHash("sha256")
|
|
47
|
+
.update(`${fingerprint}|${JSON.stringify({ cascade: options.cascade === true })}`)
|
|
48
|
+
.digest("hex");
|
|
49
|
+
}
|
|
50
|
+
const REQUEST = (fingerprint) => ({ type: "SHIP_REQUESTED", source: "system", fingerprint, occurredAt: "1970-01-01T00:00:00.000Z" });
|
|
51
|
+
function snapshotOf(actor, count) {
|
|
52
|
+
const snap = actor.getSnapshot();
|
|
53
|
+
return {
|
|
54
|
+
proposalId: snap.context.proposalId,
|
|
55
|
+
state: String(snap.value),
|
|
56
|
+
status: String(snap.status),
|
|
57
|
+
context: { ...snap.context, challengeCount: count },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Rebuild a live actor from a persisted snapshot by deterministic replay:
|
|
62
|
+
* challenged = one request with the persisted signature, confirmed = two.
|
|
63
|
+
* Terminal contexts never block later cycles (review: cycle semantics) — a
|
|
64
|
+
* new ship call on a still-controlled proposal starts fresh.
|
|
65
|
+
*/
|
|
66
|
+
function hydrate(persisted, proposalId) {
|
|
67
|
+
const count = persisted?.context.challengeCount ?? 0;
|
|
68
|
+
const actor = createShipAuditActor(proposalId);
|
|
69
|
+
const fingerprint = persisted?.context.fingerprint ?? null;
|
|
70
|
+
if (!fingerprint)
|
|
71
|
+
return { actor, count };
|
|
72
|
+
if (persisted?.state === "challenged") {
|
|
73
|
+
actor.send(REQUEST(fingerprint));
|
|
74
|
+
}
|
|
75
|
+
else if (persisted?.state === "confirmed") {
|
|
76
|
+
actor.send(REQUEST(fingerprint));
|
|
77
|
+
actor.send(REQUEST(fingerprint));
|
|
78
|
+
}
|
|
79
|
+
return { actor, count };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The deterministic ship gate (models/ship-audit.md):
|
|
83
|
+
* - challenge disabled → proceed unchanged (N1)
|
|
84
|
+
* - force → human bypass, recorded (N6) — the record MUST persist, so a
|
|
85
|
+
* store failure blocks the bypass instead of silently losing evidence
|
|
86
|
+
* - first call → AUDIT_REQUIRED, nothing executes (N2)
|
|
87
|
+
* - unchanged call (same decision AND same options) → proceed, with a
|
|
88
|
+
* `consume()` that spends the single confirmation (N3, INV-6)
|
|
89
|
+
* - changed decision or options → re-challenge (N4)
|
|
90
|
+
* - concurrent gate for the same proposal → blocked while claimed (INV-6)
|
|
91
|
+
*/
|
|
92
|
+
export async function evaluateShipAuditChallenge(input) {
|
|
93
|
+
if (!input.challengeEnabled)
|
|
94
|
+
return { proceed: true };
|
|
95
|
+
const claim = await input.store.claim(input.proposal.id);
|
|
96
|
+
if (!claim.acquired) {
|
|
97
|
+
return {
|
|
98
|
+
proceed: false,
|
|
99
|
+
message: `A concurrent ship gate for proposal #${input.proposal.id} is in flight; retry once it completes.`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return await gate(input);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await claim.release();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function gate(input) {
|
|
110
|
+
const persisted = await input.store.load(input.proposal.id).catch(() => null);
|
|
111
|
+
const { actor, count } = hydrate(persisted, input.proposal.id);
|
|
112
|
+
if (input.force) {
|
|
113
|
+
actor.send({
|
|
114
|
+
type: "FORCE_OVERRIDE",
|
|
115
|
+
source: "human",
|
|
116
|
+
reason: input.forceReason ?? "operator force",
|
|
117
|
+
occurredAt: input.occurredAt ?? new Date().toISOString(),
|
|
118
|
+
});
|
|
119
|
+
// A bypass is only as good as its record: fail closed if it cannot persist.
|
|
120
|
+
await input.store.save(snapshotOf(actor, count));
|
|
121
|
+
return { proceed: true, note: "ship audit bypassed by force (recorded)" };
|
|
122
|
+
}
|
|
123
|
+
const fingerprint = computeShipFingerprint(input.proposal);
|
|
124
|
+
const signature = requestSignature(fingerprint, input.options ?? {});
|
|
125
|
+
actor.send({ ...REQUEST(signature), occurredAt: input.occurredAt ?? new Date().toISOString() });
|
|
126
|
+
// The historical challenge counter lives here (the actor's own counter is
|
|
127
|
+
// per-cycle): a new challenge — first of a cycle or a re-challenge after a
|
|
128
|
+
// changed decision or options — increments it; a confirmation does not.
|
|
129
|
+
const stateAfterRequest = String(actor.getSnapshot().value);
|
|
130
|
+
const liveCount = stateAfterRequest === "challenged" ? count + 1 : count;
|
|
131
|
+
await input.store.save(snapshotOf(actor, liveCount));
|
|
132
|
+
const decision = computeShipAuditDecision(actor.getSnapshot().value);
|
|
133
|
+
if (decision === "PROCEED") {
|
|
134
|
+
return {
|
|
135
|
+
proceed: true,
|
|
136
|
+
consume: async () => {
|
|
137
|
+
actor.send({ type: "SHIP_CONSUMED", source: "system", occurredAt: new Date().toISOString() });
|
|
138
|
+
await input.store.save(snapshotOf(actor, liveCount));
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (decision === "BLOCKED") {
|
|
143
|
+
const state = String(actor.getSnapshot().value);
|
|
144
|
+
return { proceed: false, message: `Ship audit context is ${state}; start a new audit cycle.` };
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
proceed: false,
|
|
148
|
+
message: [
|
|
149
|
+
`AUDIT_REQUIRED — ship challenge ${liveCount} for proposal #${input.proposal.id}.`,
|
|
150
|
+
"The first call never executes. Re-read the proposal and the control results, then call dao_ship again unchanged — the same decision AND the same options (cascade).",
|
|
151
|
+
`Fingerprint: ${fingerprint.slice(0, 12)}… — any change to the decision (votes, gates, scope) or the options re-issues the challenge.`,
|
|
152
|
+
].join("\n"),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=ship-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship-audit.js","sourceRoot":"","sources":["../../src/delivery/ship-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dry-run.d.ts","sourceRoot":"","sources":["../../src/domain/dry-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAWhE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAetE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PROPOSAL_TYPE } from "../types/index.js";
|
|
2
|
+
const DURATION_BY_TYPE = {
|
|
3
|
+
[PROPOSAL_TYPE.PRODUCT_FEATURE]: "3-7 days",
|
|
4
|
+
[PROPOSAL_TYPE.SECURITY_CHANGE]: "1-2 weeks",
|
|
5
|
+
[PROPOSAL_TYPE.TECHNICAL_CHANGE]: "2-5 days",
|
|
6
|
+
[PROPOSAL_TYPE.RELEASE_CHANGE]: "1-3 days",
|
|
7
|
+
[PROPOSAL_TYPE.GOVERNANCE_CHANGE]: "1-2 days",
|
|
8
|
+
};
|
|
9
|
+
export function analyzeProposalDryRun(proposal) {
|
|
10
|
+
const filesAffected = [...(proposal.affectedPaths ?? [])];
|
|
11
|
+
const risks = [];
|
|
12
|
+
if (proposal.type === PROPOSAL_TYPE.SECURITY_CHANGE)
|
|
13
|
+
risks.push("Security-sensitive changes require extra review");
|
|
14
|
+
if (proposal.riskZone === "red")
|
|
15
|
+
risks.push("Red-zone proposal: high risk detected");
|
|
16
|
+
if (!proposal.acceptanceCriteria?.length)
|
|
17
|
+
risks.push("No acceptance criteria defined");
|
|
18
|
+
const estimatedDuration = DURATION_BY_TYPE[proposal.type];
|
|
19
|
+
return {
|
|
20
|
+
proposalId: proposal.id,
|
|
21
|
+
preview: `This proposal would modify ${filesAffected.length || "unknown number of"} files and requires ${estimatedDuration}.`,
|
|
22
|
+
filesAffected,
|
|
23
|
+
risks,
|
|
24
|
+
estimatedDuration,
|
|
25
|
+
canProceed: !risks.some((risk) => risk.includes("high risk") || risk.includes("Security-sensitive")),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=dry-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dry-run.js","sourceRoot":"","sources":["../../src/domain/dry-run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,gBAAgB,GAAqC;IACzD,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,UAAU;IAC3C,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,WAAW;IAC5C,CAAC,aAAa,CAAC,gBAAgB,CAAC,EAAE,UAAU;IAC5C,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,UAAU;IAC1C,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE,UAAU;CAC9C,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,QAAkB;IACtD,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,QAAQ,CAAC,IAAI,KAAK,aAAa,CAAC,eAAe;QAAE,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACnH,IAAI,QAAQ,CAAC,QAAQ,KAAK,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACrF,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACvF,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO;QACL,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,OAAO,EAAE,8BAA8B,aAAa,CAAC,MAAM,IAAI,mBAAmB,uBAAuB,iBAAiB,GAAG;QAC7H,aAAa;QACb,KAAK;QACL,iBAAiB;QACjB,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;KACrG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAEA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Pure domain surface. These modules contain calculations and rules only.
|
|
2
|
+
export * from "../delivery/dependencies.js";
|
|
3
|
+
export * from "../governance/lifecycle.js";
|
|
4
|
+
export * from "../governance/scoring.js";
|
|
5
|
+
export * from "../governance/voting.js";
|
|
6
|
+
export * from "./dry-run.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/governance/agents.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/governance/agents.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,eAAO,MAAM,cAAc,EAAE,QAAQ,EAoJpC,CAAC;AAgEF,gFAAgF;AAChF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AA+DD,wBAAsB,gCAAgC,CACpD,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,QAAQ,EAAmB,GACtC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAiDrB;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA2B9G;AA2BD,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAStE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAM5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAMvD;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE/D"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { promises as fs } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { filterEnabledAgents } from "../config.js";
|
|
7
|
+
import { AGENT_CHARTER, composeSystemPrompt } from "./charter.js";
|
|
7
8
|
export const DEFAULT_AGENT_MODEL = "z.ai/GLM-5.1";
|
|
8
9
|
export const DEFAULT_AGENTS = [
|
|
9
10
|
{
|
|
@@ -20,27 +21,7 @@ For each proposal, analyze:
|
|
|
20
21
|
1. Strategic alignment — does this fit the product vision?
|
|
21
22
|
2. Objectives — which OKRs or goals does this advance?
|
|
22
23
|
3. Hypotheses — what assumptions underlie this proposal?
|
|
23
|
-
4. Opportunity cost — what are we NOT doing if we do this
|
|
24
|
-
|
|
25
|
-
Output format:
|
|
26
|
-
## Analysis
|
|
27
|
-
[Your strategic analysis]
|
|
28
|
-
|
|
29
|
-
## Vote
|
|
30
|
-
for | against | abstain
|
|
31
|
-
|
|
32
|
-
## Reasoning
|
|
33
|
-
[Why you voted this way]
|
|
34
|
-
|
|
35
|
-
## Composite Score Inputs (0-10)
|
|
36
|
-
- userImpact: [0-10]
|
|
37
|
-
- businessImpact: [0-10]
|
|
38
|
-
- effort: [0-10] (lower = less effort)
|
|
39
|
-
- securityRisk: [0-10] (lower = less risk)
|
|
40
|
-
- confidence: [0-10]
|
|
41
|
-
|
|
42
|
-
## Risk Score (1-10)
|
|
43
|
-
[Overall risk assessment]`,
|
|
24
|
+
4. Opportunity cost — what are we NOT doing if we do this?`,
|
|
44
25
|
riskLevel: "medium",
|
|
45
26
|
councils: [{ council: "product-council", role: "lead" }],
|
|
46
27
|
enabled: true,
|
|
@@ -59,27 +40,7 @@ For each proposal, research:
|
|
|
59
40
|
1. Market context — trends, market size, growth
|
|
60
41
|
2. Competition — what are competitors doing?
|
|
61
42
|
3. User signals — feedback, requests, pain points
|
|
62
|
-
4. Data availability — do we have evidence to support this
|
|
63
|
-
|
|
64
|
-
Output format:
|
|
65
|
-
## Analysis
|
|
66
|
-
[Your research findings]
|
|
67
|
-
|
|
68
|
-
## Vote
|
|
69
|
-
for | against | abstain
|
|
70
|
-
|
|
71
|
-
## Reasoning
|
|
72
|
-
[Why you voted this way]
|
|
73
|
-
|
|
74
|
-
## Composite Score Inputs (0-10)
|
|
75
|
-
- userImpact: [0-10]
|
|
76
|
-
- businessImpact: [0-10]
|
|
77
|
-
- effort: [0-10]
|
|
78
|
-
- securityRisk: [0-10]
|
|
79
|
-
- confidence: [0-10]
|
|
80
|
-
|
|
81
|
-
## Risk Score (1-10)
|
|
82
|
-
[Overall risk assessment]`,
|
|
43
|
+
4. Data availability — do we have evidence to support this?`,
|
|
83
44
|
riskLevel: "low",
|
|
84
45
|
councils: [{ council: "product-council", role: "member" }],
|
|
85
46
|
enabled: true,
|
|
@@ -99,27 +60,7 @@ For each proposal, analyze:
|
|
|
99
60
|
2. Architecture impact — how does this affect system design?
|
|
100
61
|
3. Tradeoffs — what are the key technical tradeoffs?
|
|
101
62
|
4. Technical debt — will this create or reduce debt?
|
|
102
|
-
5. Scalability — will this scale with our growth
|
|
103
|
-
|
|
104
|
-
Output format:
|
|
105
|
-
## Analysis
|
|
106
|
-
[Your technical analysis]
|
|
107
|
-
|
|
108
|
-
## Vote
|
|
109
|
-
for | against | abstain
|
|
110
|
-
|
|
111
|
-
## Reasoning
|
|
112
|
-
[Why you voted this way]
|
|
113
|
-
|
|
114
|
-
## Composite Score Inputs (0-10)
|
|
115
|
-
- userImpact: [0-10]
|
|
116
|
-
- businessImpact: [0-10]
|
|
117
|
-
- effort: [0-10]
|
|
118
|
-
- securityRisk: [0-10]
|
|
119
|
-
- confidence: [0-10]
|
|
120
|
-
|
|
121
|
-
## Risk Score (1-10)
|
|
122
|
-
[Overall risk assessment]`,
|
|
63
|
+
5. Scalability — will this scale with our growth?`,
|
|
123
64
|
riskLevel: "medium",
|
|
124
65
|
councils: [{ council: "delivery-council", role: "lead" }],
|
|
125
66
|
enabled: true,
|
|
@@ -139,27 +80,7 @@ For each proposal, scrutinize:
|
|
|
139
80
|
2. Edge cases — what scenarios aren't covered?
|
|
140
81
|
3. Guardrails — are sufficient protections in place?
|
|
141
82
|
4. Downside — what's the worst-case outcome?
|
|
142
|
-
5. Unknown unknowns — what haven't we considered
|
|
143
|
-
|
|
144
|
-
Output format:
|
|
145
|
-
## Analysis
|
|
146
|
-
[Your risk analysis and objections]
|
|
147
|
-
|
|
148
|
-
## Vote
|
|
149
|
-
for | against | abstain
|
|
150
|
-
|
|
151
|
-
## Reasoning
|
|
152
|
-
[Why you voted this way]
|
|
153
|
-
|
|
154
|
-
## Composite Score Inputs (0-10)
|
|
155
|
-
- userImpact: [0-10]
|
|
156
|
-
- businessImpact: [0-10]
|
|
157
|
-
- effort: [0-10]
|
|
158
|
-
- securityRisk: [0-10]
|
|
159
|
-
- confidence: [0-10]
|
|
160
|
-
|
|
161
|
-
## Risk Score (1-10)
|
|
162
|
-
[Overall risk assessment]`,
|
|
83
|
+
5. Unknown unknowns — what haven't we considered?`,
|
|
163
84
|
riskLevel: "high",
|
|
164
85
|
councils: [
|
|
165
86
|
{ council: "security-council", role: "lead" },
|
|
@@ -182,27 +103,7 @@ For each proposal, score:
|
|
|
182
103
|
2. Cost — implementation effort, maintenance burden
|
|
183
104
|
3. Risk — probability of failure, downside exposure
|
|
184
105
|
4. Roadmap fit — does this belong in our current sequence?
|
|
185
|
-
5. Urgency — how time-sensitive is this
|
|
186
|
-
|
|
187
|
-
Output format:
|
|
188
|
-
## Analysis
|
|
189
|
-
[Your prioritization analysis]
|
|
190
|
-
|
|
191
|
-
## Vote
|
|
192
|
-
for | against | abstain
|
|
193
|
-
|
|
194
|
-
## Reasoning
|
|
195
|
-
[Why you voted this way]
|
|
196
|
-
|
|
197
|
-
## Composite Score Inputs (0-10)
|
|
198
|
-
- userImpact: [0-10]
|
|
199
|
-
- businessImpact: [0-10]
|
|
200
|
-
- effort: [0-10]
|
|
201
|
-
- securityRisk: [0-10]
|
|
202
|
-
- confidence: [0-10]
|
|
203
|
-
|
|
204
|
-
## Risk Score (1-10)
|
|
205
|
-
[Overall risk assessment]`,
|
|
106
|
+
5. Urgency — how time-sensitive is this?`,
|
|
206
107
|
riskLevel: "low",
|
|
207
108
|
councils: [{ council: "product-council", role: "member" }],
|
|
208
109
|
enabled: true,
|
|
@@ -222,27 +123,7 @@ For each proposal, assess:
|
|
|
222
123
|
2. Completeness — what's missing from the spec?
|
|
223
124
|
3. Testability — can we write acceptance criteria?
|
|
224
125
|
4. User stories — can this be broken into stories?
|
|
225
|
-
5. Edge cases — are boundary conditions defined
|
|
226
|
-
|
|
227
|
-
Output format:
|
|
228
|
-
## Analysis
|
|
229
|
-
[Your specification analysis]
|
|
230
|
-
|
|
231
|
-
## Vote
|
|
232
|
-
for | against | abstain
|
|
233
|
-
|
|
234
|
-
## Reasoning
|
|
235
|
-
[Why you voted this way]
|
|
236
|
-
|
|
237
|
-
## Composite Score Inputs (0-10)
|
|
238
|
-
- userImpact: [0-10]
|
|
239
|
-
- businessImpact: [0-10]
|
|
240
|
-
- effort: [0-10]
|
|
241
|
-
- securityRisk: [0-10]
|
|
242
|
-
- confidence: [0-10]
|
|
243
|
-
|
|
244
|
-
## Risk Score (1-10)
|
|
245
|
-
[Overall risk assessment]`,
|
|
126
|
+
5. Edge cases — are boundary conditions defined?`,
|
|
246
127
|
riskLevel: "low",
|
|
247
128
|
councils: [{ council: "product-council", role: "advisor" }],
|
|
248
129
|
enabled: true,
|
|
@@ -262,27 +143,7 @@ For each proposal, plan:
|
|
|
262
143
|
2. Task breakdown — what are the key tasks?
|
|
263
144
|
3. Effort estimate — rough timeline and resources
|
|
264
145
|
4. CI/CD impact — how does this affect pipelines?
|
|
265
|
-
5. Dependencies — what must happen first
|
|
266
|
-
|
|
267
|
-
Output format:
|
|
268
|
-
## Analysis
|
|
269
|
-
[Your delivery analysis]
|
|
270
|
-
|
|
271
|
-
## Vote
|
|
272
|
-
for | against | abstain
|
|
273
|
-
|
|
274
|
-
## Reasoning
|
|
275
|
-
[Why you voted this way]
|
|
276
|
-
|
|
277
|
-
## Composite Score Inputs (0-10)
|
|
278
|
-
- userImpact: [0-10]
|
|
279
|
-
- businessImpact: [0-10]
|
|
280
|
-
- effort: [0-10]
|
|
281
|
-
- securityRisk: [0-10]
|
|
282
|
-
- confidence: [0-10]
|
|
283
|
-
|
|
284
|
-
## Risk Score (1-10)
|
|
285
|
-
[Overall risk assessment]`,
|
|
146
|
+
5. Dependencies — what must happen first?`,
|
|
286
147
|
riskLevel: "medium",
|
|
287
148
|
councils: [{ council: "delivery-council", role: "member" }],
|
|
288
149
|
enabled: true,
|
|
@@ -291,7 +152,7 @@ for | against | abstain
|
|
|
291
152
|
function parseAgentFrontmatter(content) {
|
|
292
153
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
293
154
|
if (!match?.[1])
|
|
294
|
-
return {};
|
|
155
|
+
return { body: content.trim() || undefined };
|
|
295
156
|
const parsed = {};
|
|
296
157
|
for (const line of match[1].split("\n")) {
|
|
297
158
|
const field = line.match(/^([A-Za-z0-9_-]+):\s*(.+)$/);
|
|
@@ -321,6 +182,11 @@ function parseAgentFrontmatter(content) {
|
|
|
321
182
|
break;
|
|
322
183
|
}
|
|
323
184
|
}
|
|
185
|
+
// The markdown body is the per-agent project layer (## Project
|
|
186
|
+
// Instructions); frontmatter fields still override agent metadata.
|
|
187
|
+
const body = content.slice(match[0].length).trim();
|
|
188
|
+
if (body)
|
|
189
|
+
parsed.body = body;
|
|
324
190
|
return parsed;
|
|
325
191
|
}
|
|
326
192
|
const agentDefinitionCache = new Map();
|
|
@@ -334,23 +200,48 @@ export function __resetAgentDefinitionCache() {
|
|
|
334
200
|
function withDefaultModel(agents) {
|
|
335
201
|
return agents.map((agent) => ({ ...agent, model: agent.model ?? DEFAULT_AGENT_MODEL }));
|
|
336
202
|
}
|
|
337
|
-
async function readAndMergeMarkdownAgents(absDir, daoEntries, baseAgents) {
|
|
203
|
+
async function readAndMergeMarkdownAgents(absDir, daoEntries, baseAgents, base) {
|
|
338
204
|
const markdownAgents = new Map();
|
|
339
|
-
|
|
205
|
+
const parsedEntries = await Promise.all(daoEntries.map(async (entry) => {
|
|
340
206
|
const content = await fs.readFile(path.join(absDir, entry), "utf-8");
|
|
341
|
-
|
|
207
|
+
return parseAgentFrontmatter(content);
|
|
208
|
+
}));
|
|
209
|
+
for (const frontmatter of parsedEntries) {
|
|
342
210
|
if (frontmatter.id) {
|
|
343
211
|
markdownAgents.set(frontmatter.id, frontmatter);
|
|
344
212
|
}
|
|
345
213
|
}
|
|
346
|
-
|
|
214
|
+
// The per-project charter layer applies to every agent (swarm-forge
|
|
215
|
+
// local-* convention: layers add to the shared law, never replace it).
|
|
216
|
+
// The closest directory wins: .dao/agents beats the repo's agents/.
|
|
217
|
+
let projectCharter = base.projectCharter;
|
|
218
|
+
if (projectCharter === null) {
|
|
219
|
+
try {
|
|
220
|
+
const charter = await fs.readFile(path.join(absDir, "charter.md"), "utf-8");
|
|
221
|
+
if (charter.trim())
|
|
222
|
+
projectCharter = charter.trim();
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// No project charter here — keep looking in the remaining dirs.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const agents = baseAgents.map((agent) => {
|
|
347
229
|
const override = markdownAgents.get(agent.id);
|
|
230
|
+
if (!override)
|
|
231
|
+
return agent;
|
|
232
|
+
// The markdown body is the agent's role definition — it REPLACES the
|
|
233
|
+
// default role prompt (consistent with the frontmatter, which already
|
|
234
|
+
// overrides name/role/model/weight). The shared charter is never
|
|
235
|
+
// replaceable: composition always prepends it.
|
|
236
|
+
const { body: _body, ...fields } = override;
|
|
348
237
|
return {
|
|
349
238
|
...agent,
|
|
350
|
-
...
|
|
351
|
-
|
|
239
|
+
...fields,
|
|
240
|
+
...(override.body ? { systemPrompt: override.body } : {}),
|
|
241
|
+
model: override.model ?? agent.model ?? DEFAULT_AGENT_MODEL,
|
|
352
242
|
};
|
|
353
243
|
});
|
|
244
|
+
return { agents, projectCharter };
|
|
354
245
|
}
|
|
355
246
|
export async function loadAgentDefinitionsFromMarkdown(agentsDir, baseAgents = DEFAULT_AGENTS) {
|
|
356
247
|
const absDir = path.resolve(agentsDir);
|
|
@@ -360,15 +251,21 @@ export async function loadAgentDefinitionsFromMarkdown(agentsDir, baseAgents = D
|
|
|
360
251
|
entries = await fs.readdir(absDir);
|
|
361
252
|
}
|
|
362
253
|
catch {
|
|
363
|
-
// Directory missing/unreadable:
|
|
364
|
-
|
|
254
|
+
// Directory missing/unreadable: do NOT cache, but still compose — a
|
|
255
|
+
// missing directory must yield the same charter-backed prompts as an
|
|
256
|
+
// existing empty one.
|
|
257
|
+
return withComposedPrompts(withDefaultModel(baseAgents), null);
|
|
365
258
|
}
|
|
366
259
|
const daoEntries = entries.filter((entry) => entry.startsWith("dao-") && entry.endsWith(".md"));
|
|
367
|
-
// Build a signature over the dao-*.md entries and
|
|
368
|
-
//
|
|
260
|
+
// Build a signature over the dao-*.md entries (and charter.md, which is
|
|
261
|
+
// also a cached layer) and their stat metadata so the cache invalidates
|
|
262
|
+
// whenever a file is added, removed, or modified.
|
|
369
263
|
let signature;
|
|
370
264
|
try {
|
|
371
|
-
const
|
|
265
|
+
const signatureEntries = [...daoEntries];
|
|
266
|
+
if (entries.includes("charter.md"))
|
|
267
|
+
signatureEntries.push("charter.md");
|
|
268
|
+
const parts = await Promise.all(signatureEntries.map(async (entry) => {
|
|
372
269
|
const fileStat = await fs.stat(path.join(absDir, entry));
|
|
373
270
|
return `${entry}:${fileStat.mtimeMs}:${fileStat.size}`;
|
|
374
271
|
}));
|
|
@@ -383,7 +280,12 @@ export async function loadAgentDefinitionsFromMarkdown(agentsDir, baseAgents = D
|
|
|
383
280
|
// Cache hit: return the merged result without re-reading files.
|
|
384
281
|
return cached.result;
|
|
385
282
|
}
|
|
386
|
-
const
|
|
283
|
+
const layers = await readAndMergeMarkdownAgents(absDir, daoEntries, withDefaultModel(baseAgents), {
|
|
284
|
+
agents: withDefaultModel(baseAgents),
|
|
285
|
+
projectCharter: null,
|
|
286
|
+
});
|
|
287
|
+
// Composition happens exactly once, at the exit.
|
|
288
|
+
const result = withComposedPrompts(layers.agents, layers.projectCharter);
|
|
387
289
|
agentDefinitionCache.set(cacheKey, { signature, result });
|
|
388
290
|
return result;
|
|
389
291
|
}
|
|
@@ -393,24 +295,60 @@ export async function loadAgentDefinitions(daoRoot, projectConfig) {
|
|
|
393
295
|
path.join(daoRoot, "..", "agents"),
|
|
394
296
|
path.join(daoRoot, "..", "..", "agents"),
|
|
395
297
|
];
|
|
396
|
-
|
|
298
|
+
// Layer collection over the candidate dirs, closest first. Composition
|
|
299
|
+
// happens exactly once, after collection, so the shared charter is never
|
|
300
|
+
// duplicated across the chain.
|
|
301
|
+
let layers = {
|
|
302
|
+
agents: withDefaultModel(DEFAULT_AGENTS),
|
|
303
|
+
projectCharter: null,
|
|
304
|
+
};
|
|
397
305
|
for (const agentsDir of candidateDirs) {
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
306
|
+
const merged = await readMarkdownLayers(agentsDir, layers);
|
|
307
|
+
// Closest layer wins: the first candidate directory holding agent
|
|
308
|
+
// definitions or a charter fully shadows the further ones, so project
|
|
309
|
+
// overrides (.dao/agents) are never replaced by repo defaults (agents/).
|
|
310
|
+
if (merged) {
|
|
311
|
+
layers = merged;
|
|
404
312
|
break;
|
|
405
313
|
}
|
|
406
314
|
}
|
|
315
|
+
const agents = withComposedPrompts(layers.agents, layers.projectCharter);
|
|
407
316
|
return projectConfig ? filterEnabledAgents(agents, projectConfig) : agents;
|
|
408
317
|
}
|
|
318
|
+
/** Apply the charter + project layers to role-level agents (composition exit). */
|
|
319
|
+
function withComposedPrompts(agents, projectCharter) {
|
|
320
|
+
// Per-agent: mixed lists (some prompts already composed, some not) compose
|
|
321
|
+
// exactly the ones that need it — composeSystemPrompt is idempotent.
|
|
322
|
+
return agents.map((agent) => ({
|
|
323
|
+
...agent,
|
|
324
|
+
systemPrompt: composeSystemPrompt(agent.systemPrompt, { projectCharter }),
|
|
325
|
+
}));
|
|
326
|
+
}
|
|
327
|
+
/** Read and merge one directory's markdown layers; null when it has none. */
|
|
328
|
+
async function readMarkdownLayers(agentsDir, base) {
|
|
329
|
+
const absDir = path.resolve(agentsDir);
|
|
330
|
+
let entries;
|
|
331
|
+
try {
|
|
332
|
+
entries = await fs.readdir(absDir);
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const daoEntries = entries.filter((entry) => entry.startsWith("dao-") && entry.endsWith(".md"));
|
|
338
|
+
const hasCharter = entries.includes("charter.md");
|
|
339
|
+
if (daoEntries.length === 0 && !hasCharter)
|
|
340
|
+
return null;
|
|
341
|
+
return readAndMergeMarkdownAgents(absDir, daoEntries, base.agents, base);
|
|
342
|
+
}
|
|
409
343
|
export function initializeAgents(customAgents) {
|
|
410
344
|
if (customAgents && customAgents.length > 0) {
|
|
411
345
|
return customAgents;
|
|
412
346
|
}
|
|
413
|
-
return DEFAULT_AGENTS.map((a) => ({
|
|
347
|
+
return DEFAULT_AGENTS.map((a) => ({
|
|
348
|
+
...a,
|
|
349
|
+
systemPrompt: composeSystemPrompt(a.systemPrompt),
|
|
350
|
+
model: a.model ?? DEFAULT_AGENT_MODEL,
|
|
351
|
+
}));
|
|
414
352
|
}
|
|
415
353
|
export function formatAgentsTable(agents) {
|
|
416
354
|
let table = "| Agent | Weight | Role |\n|-------|--------|------|\n";
|
|
@@ -427,6 +365,6 @@ export function formatAgentCard(agent) {
|
|
|
427
365
|
- **Description:** ${agent.description}`;
|
|
428
366
|
}
|
|
429
367
|
export function getDefaultAgentPrompts() {
|
|
430
|
-
return Object.fromEntries(DEFAULT_AGENTS.map((a) => [a.id, a.systemPrompt]));
|
|
368
|
+
return Object.fromEntries(DEFAULT_AGENTS.map((a) => [a.id, composeSystemPrompt(a.systemPrompt)]));
|
|
431
369
|
}
|
|
432
370
|
//# sourceMappingURL=agents.js.map
|