@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
|
@@ -1,289 +1,243 @@
|
|
|
1
|
+
import { createExecutionWorkspace } from "../adapters/git-workspace.js";
|
|
2
|
+
import { LegacyDaoStateRepository } from "../adapters/persistence/legacy-dao-state.repository.js";
|
|
3
|
+
import { FsShipAuditStore } from "../adapters/ship-audit/fs-ship-audit.store.js";
|
|
4
|
+
import { InitializeDaoUseCase } from "../application/initialize-dao.use-case.js";
|
|
5
|
+
import { ControlProposalUseCase } from "../application/proposals/control-proposal.use-case.js";
|
|
6
|
+
import { CreateAmendmentProposalUseCase } from "../application/proposals/create-amendment-proposal.use-case.js";
|
|
7
|
+
import { CreateProposalUseCase } from "../application/proposals/create-proposal.use-case.js";
|
|
8
|
+
import { DeliberateProposalUseCase } from "../application/proposals/deliberate-proposal.use-case.js";
|
|
9
|
+
import { DryRunProposalUseCase } from "../application/proposals/dry-run-proposal.use-case.js";
|
|
10
|
+
import { ExecuteProposalUseCase } from "../application/proposals/execute-proposal.use-case.js";
|
|
11
|
+
import { RateProposalUseCase } from "../application/proposals/rate-proposal.use-case.js";
|
|
12
|
+
import { RecordDeliberationOutputsUseCase } from "../application/proposals/record-deliberation-outputs.use-case.js";
|
|
13
|
+
import { RollbackProposalUseCase } from "../application/proposals/rollback-proposal.use-case.js";
|
|
14
|
+
import { RoundTableUseCase } from "../application/proposals/round-table.use-case.js";
|
|
15
|
+
import { ShipProposalUseCase } from "../application/proposals/ship-proposal.use-case.js";
|
|
16
|
+
import { StartDeliberationUseCase } from "../application/proposals/start-deliberation.use-case.js";
|
|
17
|
+
import { UpdateProposalUseCase } from "../application/proposals/update-proposal.use-case.js";
|
|
1
18
|
import { loadConfig } from "../config.js";
|
|
2
19
|
import { formatAuditTrail } from "../control/audit.js";
|
|
3
|
-
import { formatControlResult, runGates } from "../control/gates.js";
|
|
4
20
|
import { formatAllArtefacts, generateAllArtefacts } from "../delivery/artefacts.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { executeProposal } from "../delivery/execution.js";
|
|
8
|
-
import { formatPlan, generateDeliveryPlan, getPlan } from "../delivery/plans.js";
|
|
21
|
+
import { formatPlan, getPlan } from "../delivery/plans.js";
|
|
22
|
+
import { evaluateShipAuditChallenge } from "../delivery/ship-audit.js";
|
|
9
23
|
import { formatAgentsTable, initializeAgents, loadAgentDefinitions } from "../governance/agents.js";
|
|
10
|
-
import {
|
|
11
|
-
import { classifyRiskZone } from "../governance/lifecycle.js";
|
|
12
|
-
import { dispatchProposalEvent } from "../governance/proposal.utils.js";
|
|
13
|
-
import { calculateCompositeScore, formatCompositeScore } from "../governance/scoring.js";
|
|
14
|
-
import { formatTallyResult, parseVoteFromOutput, tallyVotes } from "../governance/voting.js";
|
|
24
|
+
import { evaluateEditGate, formatEditGate } from "../governance/edit-gate.js";
|
|
15
25
|
import { computeHealthScore, formatHealthScore, generateDashboard } from "../health-score.js";
|
|
16
26
|
import { ghBranchNameFor, ghCreateBranch, ghCreatePullRequest, isGitHubEnabled } from "../integrations/github.js";
|
|
17
|
-
import { formatRoundTableResults
|
|
18
|
-
import { buildDispatchInstructions, createDispatchModelContext,
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
27
|
+
import { formatRoundTableResults } from "../intelligence/roundtable.js";
|
|
28
|
+
import { buildDispatchInstructions, createDispatchModelContext, formatDispatchPlan } from "../intelligence/swarm.js";
|
|
29
|
+
import { recordProposalExecuted } from "../observability/metrics.js";
|
|
30
|
+
import { getAllAuditLog, getOrCreateState, getProposal, getState, initStorage } from "../persistence.js";
|
|
31
|
+
import { systemClock } from "../ports/clock.js";
|
|
32
|
+
import { presentAmendment, presentControl, presentDeliberation, presentDryRun, presentExecution, presentInitialization, presentProposalCreated, presentProposalUpdated, presentRating, presentRollback, presentShip, } from "../presenters/proposal.presenter.js";
|
|
33
|
+
import { PROPOSAL_TYPES } from "../types/index.js";
|
|
22
34
|
import { loadGitHubConfigFromDaoRoot, saveGitHubConfigToDaoRoot } from "./github-config.js";
|
|
23
35
|
import { DAO_ONBOARDING_MESSAGE } from "./messages.js";
|
|
24
36
|
import { parseSafeJson } from "./utils.js";
|
|
25
|
-
function
|
|
26
|
-
|
|
37
|
+
function repositoryOrLegacy(repository) {
|
|
38
|
+
return repository ?? new LegacyDaoStateRepository();
|
|
39
|
+
}
|
|
40
|
+
function requireInitialized(repository) {
|
|
41
|
+
const state = repository ? repository.get() : getState();
|
|
27
42
|
if (!state.initialized)
|
|
28
43
|
return DAO_ONBOARDING_MESSAGE;
|
|
29
44
|
return null;
|
|
30
45
|
}
|
|
31
46
|
export async function handleDaoSetup(ctx, useDefaults = true) {
|
|
32
47
|
await initStorage(ctx.workDir);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return `DAO already initialized with ${state.agents.length} agents.`;
|
|
36
|
-
}
|
|
48
|
+
if (!ctx.repository)
|
|
49
|
+
getOrCreateState(ctx.workDir);
|
|
37
50
|
const agents = initializeAgents(useDefaults ? undefined : []);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
await saveState();
|
|
41
|
-
return `# DAO Initialized\n\n${formatAgentsTable(agents)}\n\nRun \`dao_help\` to discover the workflow, then \`dao_propose\` to create proposals.`;
|
|
51
|
+
const result = await new InitializeDaoUseCase({ repository: repositoryOrLegacy(ctx.repository) }).execute({ agents });
|
|
52
|
+
return presentInitialization(result);
|
|
42
53
|
}
|
|
43
|
-
export async function handleDaoPropose(args) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
proposal.problemStatement = args.problemStatement;
|
|
50
|
-
if (args.acceptanceCriteria !== undefined)
|
|
51
|
-
proposal.acceptanceCriteria = args.acceptanceCriteria;
|
|
52
|
-
if (args.successMetrics !== undefined)
|
|
53
|
-
proposal.successMetrics = args.successMetrics;
|
|
54
|
-
if (args.rollbackConditions !== undefined)
|
|
55
|
-
proposal.rollbackConditions = args.rollbackConditions;
|
|
56
|
-
if (args.affectedPaths !== undefined)
|
|
57
|
-
proposal.affectedPaths = args.affectedPaths;
|
|
58
|
-
proposal.riskZone = classifyRiskZone(proposal);
|
|
59
|
-
await saveState();
|
|
60
|
-
await recordAudit(proposal.id, "governance", "proposal_created", "user", `Proposal "${args.title}" created`);
|
|
61
|
-
const typeLabel = PROPOSAL_TYPE_LABELS[args.type] ?? args.type;
|
|
62
|
-
return `# 📋 Proposal Created — #${proposal.id}\n\n**Title:** ${args.title}\n**Type:** ${typeLabel}\n**Zone:** ${proposal.riskZone}\n\nRun \`dao_deliberate proposalId=${proposal.id}\``;
|
|
54
|
+
export async function handleDaoPropose(args, repository) {
|
|
55
|
+
const useCase = new CreateProposalUseCase({ repository: repositoryOrLegacy(repository), clock: systemClock });
|
|
56
|
+
const result = await useCase.execute({ ...args, proposedBy: "user" });
|
|
57
|
+
if (!result.ok)
|
|
58
|
+
return result.error === "DAO not initialized. Run dao_setup first." ? DAO_ONBOARDING_MESSAGE : result.error;
|
|
59
|
+
return presentProposalCreated(result.proposal);
|
|
63
60
|
}
|
|
64
61
|
export async function handleDaoDeliberate(ctx, proposalId) {
|
|
65
|
-
const notReady = requireInitialized();
|
|
62
|
+
const notReady = requireInitialized(ctx.repository);
|
|
66
63
|
if (notReady)
|
|
67
64
|
return notReady;
|
|
68
|
-
const state =
|
|
69
|
-
const proposal =
|
|
65
|
+
const state = repositoryOrLegacy(ctx.repository).get();
|
|
66
|
+
const proposal = state.proposals.find((candidate) => candidate.id === proposalId);
|
|
70
67
|
if (!proposal)
|
|
71
68
|
return `Proposal #${proposalId} not found.`;
|
|
72
69
|
if (proposal.status !== "open")
|
|
73
70
|
return `Proposal #${proposal.id} is ${proposal.status}, must be open.`;
|
|
74
|
-
const deliberation = dispatchProposalEvent(proposal, { type: "DELIBERATE" });
|
|
75
|
-
if (!deliberation.ok)
|
|
76
|
-
return `Cannot deliberate: ${deliberation.error}`;
|
|
77
|
-
await recordAudit(proposal.id, "governance", "deliberation_started", "system", `Deliberation on #${proposal.id}`);
|
|
78
|
-
await saveState();
|
|
79
71
|
const projectConfig = await loadConfig(state.daoRoot);
|
|
80
72
|
const agents = await loadAgentDefinitions(state.daoRoot, projectConfig);
|
|
81
|
-
const modelContext = createDispatchModelContext(state.config.defaultModel, ctx.adapter, {
|
|
82
|
-
parentSessionModel: ctx.getSessionModel?.(),
|
|
83
|
-
hostDefaultModel: ctx.hostDefaultModel,
|
|
84
|
-
});
|
|
85
73
|
if (ctx.deliberationMode === "manual") {
|
|
74
|
+
const deliberation = await new StartDeliberationUseCase({
|
|
75
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
76
|
+
clock: systemClock,
|
|
77
|
+
}).execute({ proposalId });
|
|
78
|
+
if (!deliberation.ok)
|
|
79
|
+
return `Cannot deliberate: ${deliberation.error}`;
|
|
80
|
+
const modelContext = createDispatchModelContext(state.config.defaultModel, ctx.adapter, {
|
|
81
|
+
parentSessionModel: ctx.getSessionModel?.(),
|
|
82
|
+
hostDefaultModel: ctx.hostDefaultModel,
|
|
83
|
+
});
|
|
86
84
|
const instructions = buildDispatchInstructions(proposal, agents, modelContext);
|
|
87
|
-
const plan = formatDispatchPlan(proposal, instructions
|
|
85
|
+
const plan = formatDispatchPlan(proposal, instructions, {
|
|
86
|
+
strategy: projectConfig.deliberation?.strategy,
|
|
87
|
+
charsPerAgent: projectConfig.deliberation?.charsPerAgent,
|
|
88
|
+
});
|
|
88
89
|
const parentModel = ctx.getSessionModel?.() ?? ctx.hostDefaultModel;
|
|
89
90
|
const parentNote = parentModel ? `\n\n**Parent session model:** ${parentModel}` : "";
|
|
90
91
|
return `${plan}${parentNote}`;
|
|
91
92
|
}
|
|
92
93
|
const startTime = Date.now();
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
await storeDeliberationBatch(proposal.id, votes, persistedOutputs);
|
|
110
|
-
}
|
|
111
|
-
proposal.votes = votes;
|
|
112
|
-
const compositeScore = calculateCompositeScore(outputs);
|
|
113
|
-
proposal.compositeScore = compositeScore;
|
|
114
|
-
await storeCompositeScore(proposal.id, compositeScore);
|
|
115
|
-
const tally = tallyVotes(proposal, state.config);
|
|
116
|
-
const synthesisText = synthesize(proposal, agents, outputs, tally);
|
|
117
|
-
proposal.synthesis = synthesisText;
|
|
118
|
-
await storeSynthesis(proposal.id, synthesisText);
|
|
119
|
-
if (tally.approved) {
|
|
120
|
-
dispatchProposalEvent(proposal, { type: "APPROVE", tally });
|
|
121
|
-
await recordAudit(proposal.id, "intelligence", "deliberation_approved", "system", `Approved: ${tally.approvalScore}%`);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
dispatchProposalEvent(proposal, { type: "REJECT" });
|
|
125
|
-
await recordAudit(proposal.id, "intelligence", "deliberation_rejected", "system", `Rejected: ${tally.approvalScore}%`);
|
|
126
|
-
}
|
|
127
|
-
await saveState();
|
|
94
|
+
const useCase = new DeliberateProposalUseCase({
|
|
95
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
96
|
+
worker: ctx.adapter,
|
|
97
|
+
clock: systemClock,
|
|
98
|
+
});
|
|
99
|
+
const result = await useCase.execute({
|
|
100
|
+
proposalId,
|
|
101
|
+
agents,
|
|
102
|
+
strategy: projectConfig.deliberation?.strategy,
|
|
103
|
+
charsPerAgent: projectConfig.deliberation?.charsPerAgent,
|
|
104
|
+
parentSessionModel: ctx.getSessionModel?.(),
|
|
105
|
+
hostDefaultModel: ctx.hostDefaultModel,
|
|
106
|
+
onUpdate: (update) => ctx.onDeliberationProgress?.(update),
|
|
107
|
+
});
|
|
108
|
+
if (!result.ok)
|
|
109
|
+
return `Cannot deliberate: ${result.error}`;
|
|
128
110
|
const duration = Date.now() - startTime;
|
|
129
|
-
return
|
|
111
|
+
return presentDeliberation(proposal.id, result, { durationMs: duration, controlToolName: ctx.controlToolName });
|
|
130
112
|
}
|
|
131
113
|
export async function handleDaoRecordOutputs(ctx, proposalId, outputs) {
|
|
132
|
-
const
|
|
114
|
+
const useCase = new RecordDeliberationOutputsUseCase({
|
|
115
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
116
|
+
clock: systemClock,
|
|
117
|
+
});
|
|
118
|
+
const result = await useCase.execute({ proposalId, outputs });
|
|
119
|
+
if (!result.ok)
|
|
120
|
+
return result.error;
|
|
121
|
+
return presentDeliberation(proposalId, result, { controlToolName: ctx.controlToolName });
|
|
122
|
+
}
|
|
123
|
+
export async function handleDaoControl(ctx, proposalId) {
|
|
124
|
+
const notReady = requireInitialized(ctx.repository);
|
|
133
125
|
if (notReady)
|
|
134
126
|
return notReady;
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
if (!
|
|
138
|
-
return
|
|
139
|
-
|
|
140
|
-
return `Expected deliberating (current: ${proposal.status})`;
|
|
141
|
-
const votes = [];
|
|
142
|
-
const enrichedOutputs = [];
|
|
143
|
-
for (const raw of outputs) {
|
|
144
|
-
const agent = state.agents.find((a) => a.id === raw.agentId);
|
|
145
|
-
if (!agent)
|
|
146
|
-
continue;
|
|
147
|
-
const output = {
|
|
148
|
-
agentId: agent.id,
|
|
149
|
-
agentName: agent.name,
|
|
150
|
-
role: agent.role,
|
|
151
|
-
content: raw.content || "",
|
|
152
|
-
durationMs: raw.durationMs ?? 0,
|
|
153
|
-
error: raw.error,
|
|
154
|
-
};
|
|
155
|
-
const vote = parseVoteFromOutput(agent.id, agent.name, agent.weight, output.content);
|
|
156
|
-
if (vote) {
|
|
157
|
-
output.vote = vote;
|
|
158
|
-
votes.push(vote);
|
|
159
|
-
}
|
|
160
|
-
enrichedOutputs.push(output);
|
|
161
|
-
}
|
|
162
|
-
await storeDeliberationBatch(proposal.id, votes, enrichedOutputs);
|
|
163
|
-
proposal.votes = votes;
|
|
164
|
-
const compositeScore = calculateCompositeScore(enrichedOutputs);
|
|
165
|
-
proposal.compositeScore = compositeScore;
|
|
166
|
-
await storeCompositeScore(proposal.id, compositeScore);
|
|
167
|
-
const synthesisText = synthesize(proposal, state.agents, enrichedOutputs);
|
|
168
|
-
proposal.synthesis = synthesisText;
|
|
169
|
-
await storeSynthesis(proposal.id, synthesisText);
|
|
170
|
-
const tally = tallyVotes(proposal, state.config);
|
|
171
|
-
if (tally.approved) {
|
|
172
|
-
dispatchProposalEvent(proposal, { type: "APPROVE", tally });
|
|
173
|
-
await recordAudit(proposal.id, "intelligence", "deliberation_approved", "system", `Approved: ${tally.approvalScore}%`);
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
dispatchProposalEvent(proposal, { type: "REJECT" });
|
|
177
|
-
await recordAudit(proposal.id, "intelligence", "deliberation_rejected", "system", `Rejected: ${tally.approvalScore}%`);
|
|
178
|
-
}
|
|
179
|
-
await saveState();
|
|
180
|
-
return `# 🗳️ Deliberation Complete — #${proposal.id}\n\n${formatTallyResult(tally)}\n\n${formatCompositeScore(compositeScore)}\n\n${synthesisText}\n\n> Next: \`${ctx.controlToolName} proposalId=${proposal.id}\``;
|
|
127
|
+
const useCase = new ControlProposalUseCase({ repository: repositoryOrLegacy(ctx.repository), clock: systemClock });
|
|
128
|
+
const result = await useCase.execute({ proposalId, failOnGateFailure: ctx.failOnGateFailure });
|
|
129
|
+
if (!result.ok)
|
|
130
|
+
return result.error;
|
|
131
|
+
return presentControl(result.control);
|
|
181
132
|
}
|
|
182
|
-
export async function
|
|
183
|
-
const
|
|
133
|
+
export async function handleDaoExecute(ctx, proposalId) {
|
|
134
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
135
|
+
const projectConfig = await loadConfig(repository.get().daoRoot);
|
|
136
|
+
const workspace = createExecutionWorkspace(projectConfig.execution, ctx.adapter, ctx.workDir);
|
|
137
|
+
const useCase = new ExecuteProposalUseCase({ repository, clock: systemClock, workspace });
|
|
138
|
+
const result = await useCase.execute({ proposalId, actor: "user" });
|
|
139
|
+
if (!result.ok)
|
|
140
|
+
return result.error;
|
|
141
|
+
recordProposalExecuted(result.proposal.id, result.proposal.type);
|
|
142
|
+
return presentExecution(result);
|
|
143
|
+
}
|
|
144
|
+
export async function handleDaoShip(ctx, proposalId, options) {
|
|
145
|
+
const notReady = requireInitialized(ctx.repository);
|
|
184
146
|
if (notReady)
|
|
185
147
|
return notReady;
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (
|
|
203
|
-
|
|
148
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
149
|
+
// Ship audit challenge (opt-in): the first call challenges instead of
|
|
150
|
+
// executing; only an unchanged second call proceeds (models/ship-audit.md).
|
|
151
|
+
const shipConfig = await loadConfig(repository.get().daoRoot);
|
|
152
|
+
if (shipConfig.ship?.auditChallenge === true) {
|
|
153
|
+
const proposal = repository.get().proposals.find((candidate) => candidate.id === proposalId);
|
|
154
|
+
if (!proposal)
|
|
155
|
+
return `Proposal #${proposalId} not found.`;
|
|
156
|
+
const gate = await evaluateShipAuditChallenge({
|
|
157
|
+
proposal,
|
|
158
|
+
store: new FsShipAuditStore(ctx.workDir),
|
|
159
|
+
challengeEnabled: true,
|
|
160
|
+
force: options?.force === true,
|
|
161
|
+
forceReason: options?.force === true ? "dao_ship force" : undefined,
|
|
162
|
+
options: { cascade: options?.cascade === true },
|
|
163
|
+
});
|
|
164
|
+
if (!gate.proceed)
|
|
165
|
+
return `# 🛑 Ship Audit — Do Not Proceed
|
|
166
|
+
|
|
167
|
+
${gate.message}
|
|
168
|
+
|
|
169
|
+
Force with an explicit reason when genuinely required: re-run with \`force=true\` (recorded as a human bypass).`;
|
|
170
|
+
// Shipping executes controlled proposals, so it must honour the same
|
|
171
|
+
// execution isolation as dao_execute — otherwise host shipping would
|
|
172
|
+
// bypass a configured worktree.
|
|
173
|
+
const workspace = createExecutionWorkspace(shipConfig.execution, ctx.adapter, ctx.workDir);
|
|
174
|
+
const auditedUseCase = new ShipProposalUseCase({ repository, clock: systemClock, workspace });
|
|
175
|
+
// The audited path: force means "bypass the audit challenge" ONLY —
|
|
176
|
+
// dependency checks still run inside the use-case (review resolution:
|
|
177
|
+
// the bypass satisfies INV-1, nothing else).
|
|
178
|
+
const auditedResult = await auditedUseCase.execute({
|
|
179
|
+
proposalId,
|
|
180
|
+
actor: ctx.adapter.hostId,
|
|
181
|
+
cascade: options?.cascade,
|
|
182
|
+
});
|
|
183
|
+
await gate.consume?.();
|
|
184
|
+
if (!auditedResult.ok)
|
|
185
|
+
return auditedResult.error;
|
|
186
|
+
for (const id of auditedResult.shipped) {
|
|
187
|
+
const shipped = repository.get().proposals.find((candidate) => candidate.id === id);
|
|
188
|
+
if (shipped)
|
|
189
|
+
recordProposalExecuted(shipped.id, shipped.type);
|
|
204
190
|
}
|
|
205
|
-
|
|
191
|
+
return `${presentShip(auditedResult)}${gate.note ? `\n\n*${gate.note}*` : ""}`;
|
|
206
192
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
193
|
+
// Shipping executes controlled proposals, so it must honour the same
|
|
194
|
+
// execution isolation as dao_execute — otherwise host shipping would
|
|
195
|
+
// bypass a configured worktree.
|
|
196
|
+
const workspace = createExecutionWorkspace(shipConfig.execution, ctx.adapter, ctx.workDir);
|
|
197
|
+
const useCase = new ShipProposalUseCase({ repository, clock: systemClock, workspace });
|
|
198
|
+
const result = await useCase.execute({
|
|
199
|
+
proposalId,
|
|
200
|
+
actor: ctx.adapter.hostId,
|
|
201
|
+
cascade: options?.cascade,
|
|
202
|
+
force: options?.force,
|
|
203
|
+
});
|
|
204
|
+
if (!result.ok)
|
|
205
|
+
return result.error;
|
|
206
|
+
for (const id of result.shipped) {
|
|
207
|
+
const proposal = repositoryOrLegacy(ctx.repository)
|
|
208
|
+
.get()
|
|
209
|
+
.proposals.find((candidate) => candidate.id === id);
|
|
210
|
+
if (proposal)
|
|
211
|
+
recordProposalExecuted(proposal.id, proposal.type);
|
|
216
212
|
}
|
|
217
|
-
|
|
218
|
-
await saveState();
|
|
219
|
-
await recordAudit(proposal.id, "delivery", "proposal_executed", "user", `Executed #${proposal.id}`);
|
|
220
|
-
return result.result;
|
|
213
|
+
return presentShip(result);
|
|
221
214
|
}
|
|
222
|
-
export async function
|
|
223
|
-
const
|
|
215
|
+
export async function handleDaoCheckEdit(ctx, paths) {
|
|
216
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
217
|
+
const notReady = requireInitialized(ctx.repository);
|
|
224
218
|
if (notReady)
|
|
225
219
|
return notReady;
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const force = options?.force === true;
|
|
232
|
-
const shipped = [];
|
|
233
|
-
const shipOne = async (id) => {
|
|
234
|
-
const target = getProposal(id);
|
|
235
|
-
if (!target)
|
|
236
|
-
return `Proposal #${id} not found.`;
|
|
237
|
-
if (target.status !== "controlled") {
|
|
238
|
-
return `Proposal #${target.id} must be in 'controlled' state to ship (current: ${target.status})`;
|
|
239
|
-
}
|
|
240
|
-
const result = await executeProposal(target);
|
|
241
|
-
if (!result.success)
|
|
242
|
-
return result.result;
|
|
243
|
-
await recordAudit(target.id, "delivery", "proposal-shipped", ctx.adapter.hostId, "shipped via dao_ship");
|
|
244
|
-
return null;
|
|
245
|
-
};
|
|
246
|
-
if (!force) {
|
|
247
|
-
const depsResolution = getUnexecutedDependencies(proposal.id, state.proposals);
|
|
248
|
-
if (depsResolution.error)
|
|
249
|
-
return depsResolution.error;
|
|
250
|
-
const pendingDeps = depsResolution.order ?? [];
|
|
251
|
-
if (pendingDeps.length > 0 && !cascade) {
|
|
252
|
-
const lines = pendingDeps.map((depId) => {
|
|
253
|
-
const dep = getProposal(depId);
|
|
254
|
-
return dep ? `- #${dep.id} [${dep.status}] ${dep.title}` : `- #${depId} [missing]`;
|
|
255
|
-
});
|
|
256
|
-
return `Cannot ship proposal #${proposal.id}: unexecuted dependencies found.\n\n${lines.join("\n")}\n\nRetry with \`dao_ship proposalId=${proposal.id} cascade=true\` or \`force=true\`.`;
|
|
257
|
-
}
|
|
258
|
-
if (cascade && pendingDeps.length > 0) {
|
|
259
|
-
const notControlled = pendingDeps.filter((depId) => getProposal(depId)?.status !== "controlled");
|
|
260
|
-
if (notControlled.length > 0) {
|
|
261
|
-
const details = notControlled
|
|
262
|
-
.map((depId) => {
|
|
263
|
-
const dep = getProposal(depId);
|
|
264
|
-
return dep ? `#${dep.id} (${dep.status})` : `#${depId} (missing)`;
|
|
265
|
-
})
|
|
266
|
-
.join(", ");
|
|
267
|
-
return `Cannot cascade ship: dependencies not in 'controlled' state: ${details}`;
|
|
268
|
-
}
|
|
269
|
-
for (const depId of pendingDeps) {
|
|
270
|
-
const dep = getProposal(depId);
|
|
271
|
-
if (!dep || dep.status === "executed")
|
|
272
|
-
continue;
|
|
273
|
-
const depError = await shipOne(depId);
|
|
274
|
-
if (depError)
|
|
275
|
-
return depError;
|
|
276
|
-
shipped.push(depId);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
220
|
+
const cleaned = [...new Set(paths.map((path) => path.trim()).filter(Boolean))];
|
|
221
|
+
// Refuse oversized requests outright: silently truncating could let a
|
|
222
|
+
// protected file ride just past the cutoff and come back as allowed.
|
|
223
|
+
if (cleaned.length > 200) {
|
|
224
|
+
return `Too many paths provided (${cleaned.length}). Pass at most 200 paths per edit check.`;
|
|
279
225
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
226
|
+
if (cleaned.length === 0)
|
|
227
|
+
return "No paths provided. Pass the files you are about to edit.";
|
|
228
|
+
const state = repository.get();
|
|
229
|
+
const projectConfig = await loadConfig(state.daoRoot);
|
|
230
|
+
const decision = evaluateEditGate({
|
|
231
|
+
paths: cleaned,
|
|
232
|
+
mode: projectConfig.mode,
|
|
233
|
+
criticalPaths: projectConfig.criticalPaths ?? [],
|
|
234
|
+
approved: state.proposals.map((proposal) => ({
|
|
235
|
+
proposalId: proposal.id,
|
|
236
|
+
affectedPaths: proposal.affectedPaths,
|
|
237
|
+
status: proposal.status,
|
|
238
|
+
})),
|
|
239
|
+
});
|
|
240
|
+
return formatEditGate(decision);
|
|
287
241
|
}
|
|
288
242
|
export async function handleDaoList() {
|
|
289
243
|
const notReady = requireInitialized();
|
|
@@ -335,117 +289,71 @@ export async function handleDaoArtefacts(proposalId) {
|
|
|
335
289
|
return `Proposal #${proposalId} not found.`;
|
|
336
290
|
return formatAllArtefacts(generateAllArtefacts(proposal));
|
|
337
291
|
}
|
|
338
|
-
export async function handleDaoDryRun(proposalId) {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
proposal.dryRunCanProceed = result.canProceed;
|
|
345
|
-
await saveState();
|
|
346
|
-
return formatDryRun(result);
|
|
292
|
+
export async function handleDaoDryRun(proposalId, repository) {
|
|
293
|
+
const result = await new DryRunProposalUseCase({
|
|
294
|
+
repository: repositoryOrLegacy(repository),
|
|
295
|
+
clock: systemClock,
|
|
296
|
+
}).execute({ proposalId });
|
|
297
|
+
return result.ok ? presentDryRun(result.analysis) : result.error;
|
|
347
298
|
}
|
|
348
|
-
export async function handleDaoRollback(proposalId) {
|
|
349
|
-
|
|
299
|
+
export async function handleDaoRollback(proposalId, repository) {
|
|
300
|
+
const result = await new RollbackProposalUseCase({ repository: repositoryOrLegacy(repository) }).execute({
|
|
301
|
+
proposalId,
|
|
302
|
+
});
|
|
303
|
+
return presentRollback(result);
|
|
350
304
|
}
|
|
351
|
-
export async function handleDaoDashboard() {
|
|
352
|
-
const notReady = requireInitialized();
|
|
305
|
+
export async function handleDaoDashboard(repository) {
|
|
306
|
+
const notReady = requireInitialized(repository);
|
|
353
307
|
if (notReady)
|
|
354
308
|
return notReady;
|
|
355
|
-
const state =
|
|
309
|
+
const state = repositoryOrLegacy(repository).get();
|
|
356
310
|
const dashboard = generateDashboard(state.proposals, state.outcomes, state.agents, state.healthSnapshots);
|
|
357
311
|
const health = computeHealthScore(state.proposals, state.outcomes, state.config.healthWeights);
|
|
358
312
|
return `${dashboard}\n\n${formatHealthScore(health)}`;
|
|
359
313
|
}
|
|
360
314
|
export async function handleDaoRoundtable(ctx) {
|
|
361
|
-
const notReady = requireInitialized();
|
|
315
|
+
const notReady = requireInitialized(ctx.repository);
|
|
362
316
|
if (notReady)
|
|
363
317
|
return notReady;
|
|
364
318
|
const state = getState();
|
|
365
319
|
const projectConfig = await loadConfig(state.daoRoot);
|
|
366
320
|
const agents = await loadAgentDefinitions(state.daoRoot, projectConfig);
|
|
367
|
-
const
|
|
321
|
+
const result = await new RoundTableUseCase({
|
|
322
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
323
|
+
worker: ctx.adapter,
|
|
324
|
+
clock: systemClock,
|
|
325
|
+
}).execute({
|
|
326
|
+
agents,
|
|
368
327
|
parentSessionModel: ctx.getSessionModel?.(),
|
|
369
328
|
hostDefaultModel: ctx.hostDefaultModel,
|
|
370
329
|
});
|
|
371
|
-
|
|
372
|
-
const proposalIds = new Map();
|
|
373
|
-
const parsedSuggestions = suggestions
|
|
374
|
-
.map((suggestion) => ({ suggestion, parsed: suggestion.parsed }))
|
|
375
|
-
.filter((entry) => Boolean(entry.parsed));
|
|
376
|
-
try {
|
|
377
|
-
const proposals = await createProposalsBatch(parsedSuggestions.map(({ suggestion, parsed }) => ({
|
|
378
|
-
title: parsed.title,
|
|
379
|
-
type: parsed.type,
|
|
380
|
-
description: parsed.description,
|
|
381
|
-
proposedBy: suggestion.agentId,
|
|
382
|
-
})));
|
|
383
|
-
for (const [index, { suggestion }] of parsedSuggestions.entries()) {
|
|
384
|
-
const proposal = proposals[index];
|
|
385
|
-
if (!proposal)
|
|
386
|
-
continue;
|
|
387
|
-
proposal.riskZone = classifyRiskZone(proposal);
|
|
388
|
-
suggestion.proposalId = proposal.id;
|
|
389
|
-
proposalIds.set(suggestion.agentId, proposal.id);
|
|
390
|
-
state.auditLog.push({
|
|
391
|
-
id: state.nextAuditId++,
|
|
392
|
-
timestamp: new Date().toISOString(),
|
|
393
|
-
proposalId: proposal.id,
|
|
394
|
-
layer: "intelligence",
|
|
395
|
-
action: "roundtable_proposal_created",
|
|
396
|
-
actor: suggestion.agentId,
|
|
397
|
-
details: "Auto-created from round table",
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
catch (error) {
|
|
402
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
403
|
-
for (const { suggestion } of parsedSuggestions) {
|
|
404
|
-
suggestion.error = `Failed to create proposal: ${message}`;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
await saveState();
|
|
408
|
-
return formatRoundTableResults(suggestions, proposalIds);
|
|
330
|
+
return result.ok ? formatRoundTableResults(result.suggestions, result.proposalIds) : result.error;
|
|
409
331
|
}
|
|
410
332
|
export async function handleDaoAudit(proposalId) {
|
|
411
333
|
const entries = proposalId ? getAllAuditLog().filter((e) => e.proposalId === proposalId) : getAllAuditLog();
|
|
412
334
|
return formatAuditTrail(entries, proposalId);
|
|
413
335
|
}
|
|
414
|
-
export async function handleDaoRate(proposalId, score, comment) {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
await addRating(proposal.id, {
|
|
421
|
-
proposalId: proposal.id,
|
|
336
|
+
export async function handleDaoRate(proposalId, score, comment, repository) {
|
|
337
|
+
const result = await new RateProposalUseCase({
|
|
338
|
+
repository: repositoryOrLegacy(repository),
|
|
339
|
+
clock: systemClock,
|
|
340
|
+
}).execute({
|
|
341
|
+
proposalId,
|
|
422
342
|
rater: "user",
|
|
423
343
|
score,
|
|
424
344
|
comment,
|
|
425
|
-
ratedAt: new Date().toISOString(),
|
|
426
345
|
});
|
|
427
|
-
|
|
428
|
-
return `# ⭐ Rating Recorded — #${proposal.id}\n\n**Score:** ${score}/5\n**Comment:** ${comment}`;
|
|
346
|
+
return result.ok ? presentRating(result.rating) : result.error;
|
|
429
347
|
}
|
|
430
|
-
export async function handleDaoUpdateProposal(proposalId, fields) {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (fields.problemStatement !== undefined)
|
|
437
|
-
proposal.problemStatement = fields.problemStatement;
|
|
438
|
-
if (fields.acceptanceCriteria !== undefined)
|
|
439
|
-
proposal.acceptanceCriteria = fields.acceptanceCriteria;
|
|
440
|
-
if (fields.successMetrics !== undefined)
|
|
441
|
-
proposal.successMetrics = fields.successMetrics;
|
|
442
|
-
if (fields.rollbackConditions !== undefined)
|
|
443
|
-
proposal.rollbackConditions = fields.rollbackConditions;
|
|
444
|
-
await saveState();
|
|
445
|
-
return `# 📝 Proposal Updated — #${proposal.id}\n\nUpdated fields applied.`;
|
|
348
|
+
export async function handleDaoUpdateProposal(proposalId, fields, repository) {
|
|
349
|
+
const result = await new UpdateProposalUseCase({ repository: repositoryOrLegacy(repository) }).execute({
|
|
350
|
+
proposalId,
|
|
351
|
+
fields,
|
|
352
|
+
});
|
|
353
|
+
return result.ok ? presentProposalUpdated(result.proposal) : result.error;
|
|
446
354
|
}
|
|
447
|
-
export async function handleDaoProposeAmendment(args) {
|
|
448
|
-
const notReady = requireInitialized();
|
|
355
|
+
export async function handleDaoProposeAmendment(args, repository) {
|
|
356
|
+
const notReady = requireInitialized(repository);
|
|
449
357
|
if (notReady)
|
|
450
358
|
return notReady;
|
|
451
359
|
let payload;
|
|
@@ -492,20 +400,16 @@ export async function handleDaoProposeAmendment(args) {
|
|
|
492
400
|
}
|
|
493
401
|
if (!payload)
|
|
494
402
|
return "Error: amendment payload could not be constructed";
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
proposal.riskZone = classifyRiskZone(proposal);
|
|
503
|
-
await saveState();
|
|
504
|
-
await recordAudit(proposal.id, "governance", "amendment_proposed", "user", `Amendment: ${payload.type}`);
|
|
505
|
-
return `# 📜 Amendment Proposed — #${proposal.id}\n\nType: ${payload.type}\n\nRun \`dao_deliberate proposalId=${proposal.id}\``;
|
|
403
|
+
const result = await new CreateAmendmentProposalUseCase({
|
|
404
|
+
repository: repositoryOrLegacy(repository),
|
|
405
|
+
clock: systemClock,
|
|
406
|
+
}).execute({ title: args.title, description: args.description, payload, proposedBy: "user" });
|
|
407
|
+
if (!result.ok)
|
|
408
|
+
return `❌ ${result.error}`;
|
|
409
|
+
return presentAmendment(result);
|
|
506
410
|
}
|
|
507
|
-
export async function handleDaoConfigGithub(
|
|
508
|
-
const state =
|
|
411
|
+
export async function handleDaoConfigGithub(ctx, args) {
|
|
412
|
+
const state = repositoryOrLegacy(ctx.repository).get();
|
|
509
413
|
await saveGitHubConfigToDaoRoot(state.daoRoot, args);
|
|
510
414
|
return [
|
|
511
415
|
`# GitHub Configured`,
|
|
@@ -517,14 +421,15 @@ export async function handleDaoConfigGithub(_ctx, args) {
|
|
|
517
421
|
"Available: `dao_github_create_branch`, `dao_github_open_pr`",
|
|
518
422
|
].join("\n");
|
|
519
423
|
}
|
|
520
|
-
export async function handleDaoGithubCreateBranch(
|
|
521
|
-
const
|
|
424
|
+
export async function handleDaoGithubCreateBranch(ctx, proposalId) {
|
|
425
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
426
|
+
const notReady = requireInitialized(ctx.repository);
|
|
522
427
|
if (notReady)
|
|
523
428
|
return notReady;
|
|
524
|
-
const proposal =
|
|
429
|
+
const proposal = repository.get().proposals.find((candidate) => candidate.id === proposalId);
|
|
525
430
|
if (!proposal)
|
|
526
431
|
return `Proposal #${proposalId} not found.`;
|
|
527
|
-
const configured = await loadGitHubConfigFromDaoRoot(
|
|
432
|
+
const configured = await loadGitHubConfigFromDaoRoot(repository.get().daoRoot);
|
|
528
433
|
if (!configured || !isGitHubEnabled()) {
|
|
529
434
|
return "GitHub not configured. Run `dao_config_github` with token, owner, and repo.";
|
|
530
435
|
}
|
|
@@ -534,16 +439,17 @@ export async function handleDaoGithubCreateBranch(_ctx, proposalId) {
|
|
|
534
439
|
return "Failed to create branch (GitHub API returned null)";
|
|
535
440
|
return `# Branch Created\n\n**Branch:** ${branchName}\n**SHA:** ${result.sha.slice(0, 7)}`;
|
|
536
441
|
}
|
|
537
|
-
export async function handleDaoGithubOpenPr(
|
|
538
|
-
const
|
|
442
|
+
export async function handleDaoGithubOpenPr(ctx, proposalId, headBranch) {
|
|
443
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
444
|
+
const notReady = requireInitialized(ctx.repository);
|
|
539
445
|
if (notReady)
|
|
540
446
|
return notReady;
|
|
541
|
-
const proposal =
|
|
447
|
+
const proposal = repository.get().proposals.find((candidate) => candidate.id === proposalId);
|
|
542
448
|
if (!proposal)
|
|
543
449
|
return `Proposal #${proposalId} not found.`;
|
|
544
450
|
if (!headBranch)
|
|
545
451
|
return "headBranch is required";
|
|
546
|
-
const configured = await loadGitHubConfigFromDaoRoot(
|
|
452
|
+
const configured = await loadGitHubConfigFromDaoRoot(repository.get().daoRoot);
|
|
547
453
|
if (!configured || !isGitHubEnabled()) {
|
|
548
454
|
return "GitHub not configured. Run `dao_config_github` with token, owner, and repo.";
|
|
549
455
|
}
|