@guyghost/swarm-dao-core 0.4.0 → 0.5.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 +6 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +6 -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/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 +17 -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 +1 -0
- package/dist/delivery/index.d.ts.map +1 -1
- package/dist/delivery/index.js +1 -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/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 +204 -343
- 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 +5 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +5 -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/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 +5 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +5 -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/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,198 @@
|
|
|
1
|
+
import { createExecutionWorkspace } from "../adapters/git-workspace.js";
|
|
2
|
+
import { LegacyDaoStateRepository } from "../adapters/persistence/legacy-dao-state.repository.js";
|
|
3
|
+
import { InitializeDaoUseCase } from "../application/initialize-dao.use-case.js";
|
|
4
|
+
import { ControlProposalUseCase } from "../application/proposals/control-proposal.use-case.js";
|
|
5
|
+
import { CreateAmendmentProposalUseCase } from "../application/proposals/create-amendment-proposal.use-case.js";
|
|
6
|
+
import { CreateProposalUseCase } from "../application/proposals/create-proposal.use-case.js";
|
|
7
|
+
import { DeliberateProposalUseCase } from "../application/proposals/deliberate-proposal.use-case.js";
|
|
8
|
+
import { DryRunProposalUseCase } from "../application/proposals/dry-run-proposal.use-case.js";
|
|
9
|
+
import { ExecuteProposalUseCase } from "../application/proposals/execute-proposal.use-case.js";
|
|
10
|
+
import { RateProposalUseCase } from "../application/proposals/rate-proposal.use-case.js";
|
|
11
|
+
import { RecordDeliberationOutputsUseCase } from "../application/proposals/record-deliberation-outputs.use-case.js";
|
|
12
|
+
import { RollbackProposalUseCase } from "../application/proposals/rollback-proposal.use-case.js";
|
|
13
|
+
import { RoundTableUseCase } from "../application/proposals/round-table.use-case.js";
|
|
14
|
+
import { ShipProposalUseCase } from "../application/proposals/ship-proposal.use-case.js";
|
|
15
|
+
import { StartDeliberationUseCase } from "../application/proposals/start-deliberation.use-case.js";
|
|
16
|
+
import { UpdateProposalUseCase } from "../application/proposals/update-proposal.use-case.js";
|
|
1
17
|
import { loadConfig } from "../config.js";
|
|
2
18
|
import { formatAuditTrail } from "../control/audit.js";
|
|
3
|
-
import { formatControlResult, runGates } from "../control/gates.js";
|
|
4
19
|
import { formatAllArtefacts, generateAllArtefacts } from "../delivery/artefacts.js";
|
|
5
|
-
import {
|
|
6
|
-
import { formatDryRun, formatRollback, performDryRun, performRollback } from "../delivery/dry-run.js";
|
|
7
|
-
import { executeProposal } from "../delivery/execution.js";
|
|
8
|
-
import { formatPlan, generateDeliveryPlan, getPlan } from "../delivery/plans.js";
|
|
20
|
+
import { formatPlan, getPlan } from "../delivery/plans.js";
|
|
9
21
|
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";
|
|
22
|
+
import { evaluateEditGate, formatEditGate } from "../governance/edit-gate.js";
|
|
15
23
|
import { computeHealthScore, formatHealthScore, generateDashboard } from "../health-score.js";
|
|
16
24
|
import { ghBranchNameFor, ghCreateBranch, ghCreatePullRequest, isGitHubEnabled } from "../integrations/github.js";
|
|
17
|
-
import { formatRoundTableResults
|
|
18
|
-
import { buildDispatchInstructions, createDispatchModelContext,
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
25
|
+
import { formatRoundTableResults } from "../intelligence/roundtable.js";
|
|
26
|
+
import { buildDispatchInstructions, createDispatchModelContext, formatDispatchPlan } from "../intelligence/swarm.js";
|
|
27
|
+
import { recordProposalExecuted } from "../observability/metrics.js";
|
|
28
|
+
import { getAllAuditLog, getOrCreateState, getProposal, getState, initStorage } from "../persistence.js";
|
|
29
|
+
import { systemClock } from "../ports/clock.js";
|
|
30
|
+
import { presentAmendment, presentControl, presentDeliberation, presentDryRun, presentExecution, presentInitialization, presentProposalCreated, presentProposalUpdated, presentRating, presentRollback, presentShip, } from "../presenters/proposal.presenter.js";
|
|
31
|
+
import { PROPOSAL_TYPES } from "../types/index.js";
|
|
22
32
|
import { loadGitHubConfigFromDaoRoot, saveGitHubConfigToDaoRoot } from "./github-config.js";
|
|
23
33
|
import { DAO_ONBOARDING_MESSAGE } from "./messages.js";
|
|
24
34
|
import { parseSafeJson } from "./utils.js";
|
|
25
|
-
function
|
|
26
|
-
|
|
35
|
+
function repositoryOrLegacy(repository) {
|
|
36
|
+
return repository ?? new LegacyDaoStateRepository();
|
|
37
|
+
}
|
|
38
|
+
function requireInitialized(repository) {
|
|
39
|
+
const state = repository ? repository.get() : getState();
|
|
27
40
|
if (!state.initialized)
|
|
28
41
|
return DAO_ONBOARDING_MESSAGE;
|
|
29
42
|
return null;
|
|
30
43
|
}
|
|
31
44
|
export async function handleDaoSetup(ctx, useDefaults = true) {
|
|
32
45
|
await initStorage(ctx.workDir);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return `DAO already initialized with ${state.agents.length} agents.`;
|
|
36
|
-
}
|
|
46
|
+
if (!ctx.repository)
|
|
47
|
+
getOrCreateState(ctx.workDir);
|
|
37
48
|
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.`;
|
|
49
|
+
const result = await new InitializeDaoUseCase({ repository: repositoryOrLegacy(ctx.repository) }).execute({ agents });
|
|
50
|
+
return presentInitialization(result);
|
|
42
51
|
}
|
|
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}\``;
|
|
52
|
+
export async function handleDaoPropose(args, repository) {
|
|
53
|
+
const useCase = new CreateProposalUseCase({ repository: repositoryOrLegacy(repository), clock: systemClock });
|
|
54
|
+
const result = await useCase.execute({ ...args, proposedBy: "user" });
|
|
55
|
+
if (!result.ok)
|
|
56
|
+
return result.error === "DAO not initialized. Run dao_setup first." ? DAO_ONBOARDING_MESSAGE : result.error;
|
|
57
|
+
return presentProposalCreated(result.proposal);
|
|
63
58
|
}
|
|
64
59
|
export async function handleDaoDeliberate(ctx, proposalId) {
|
|
65
|
-
const notReady = requireInitialized();
|
|
60
|
+
const notReady = requireInitialized(ctx.repository);
|
|
66
61
|
if (notReady)
|
|
67
62
|
return notReady;
|
|
68
|
-
const state =
|
|
69
|
-
const proposal =
|
|
63
|
+
const state = repositoryOrLegacy(ctx.repository).get();
|
|
64
|
+
const proposal = state.proposals.find((candidate) => candidate.id === proposalId);
|
|
70
65
|
if (!proposal)
|
|
71
66
|
return `Proposal #${proposalId} not found.`;
|
|
72
67
|
if (proposal.status !== "open")
|
|
73
68
|
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
69
|
const projectConfig = await loadConfig(state.daoRoot);
|
|
80
70
|
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
71
|
if (ctx.deliberationMode === "manual") {
|
|
72
|
+
const deliberation = await new StartDeliberationUseCase({
|
|
73
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
74
|
+
clock: systemClock,
|
|
75
|
+
}).execute({ proposalId });
|
|
76
|
+
if (!deliberation.ok)
|
|
77
|
+
return `Cannot deliberate: ${deliberation.error}`;
|
|
78
|
+
const modelContext = createDispatchModelContext(state.config.defaultModel, ctx.adapter, {
|
|
79
|
+
parentSessionModel: ctx.getSessionModel?.(),
|
|
80
|
+
hostDefaultModel: ctx.hostDefaultModel,
|
|
81
|
+
});
|
|
86
82
|
const instructions = buildDispatchInstructions(proposal, agents, modelContext);
|
|
87
|
-
const plan = formatDispatchPlan(proposal, instructions
|
|
83
|
+
const plan = formatDispatchPlan(proposal, instructions, {
|
|
84
|
+
strategy: projectConfig.deliberation?.strategy,
|
|
85
|
+
charsPerAgent: projectConfig.deliberation?.charsPerAgent,
|
|
86
|
+
});
|
|
88
87
|
const parentModel = ctx.getSessionModel?.() ?? ctx.hostDefaultModel;
|
|
89
88
|
const parentNote = parentModel ? `\n\n**Parent session model:** ${parentModel}` : "";
|
|
90
89
|
return `${plan}${parentNote}`;
|
|
91
90
|
}
|
|
92
91
|
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();
|
|
92
|
+
const useCase = new DeliberateProposalUseCase({
|
|
93
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
94
|
+
worker: ctx.adapter,
|
|
95
|
+
clock: systemClock,
|
|
96
|
+
});
|
|
97
|
+
const result = await useCase.execute({
|
|
98
|
+
proposalId,
|
|
99
|
+
agents,
|
|
100
|
+
strategy: projectConfig.deliberation?.strategy,
|
|
101
|
+
charsPerAgent: projectConfig.deliberation?.charsPerAgent,
|
|
102
|
+
parentSessionModel: ctx.getSessionModel?.(),
|
|
103
|
+
hostDefaultModel: ctx.hostDefaultModel,
|
|
104
|
+
onUpdate: (update) => ctx.onDeliberationProgress?.(update),
|
|
105
|
+
});
|
|
106
|
+
if (!result.ok)
|
|
107
|
+
return `Cannot deliberate: ${result.error}`;
|
|
128
108
|
const duration = Date.now() - startTime;
|
|
129
|
-
return
|
|
109
|
+
return presentDeliberation(proposal.id, result, { durationMs: duration, controlToolName: ctx.controlToolName });
|
|
130
110
|
}
|
|
131
111
|
export async function handleDaoRecordOutputs(ctx, proposalId, outputs) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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}\``;
|
|
112
|
+
const useCase = new RecordDeliberationOutputsUseCase({
|
|
113
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
114
|
+
clock: systemClock,
|
|
115
|
+
});
|
|
116
|
+
const result = await useCase.execute({ proposalId, outputs });
|
|
117
|
+
if (!result.ok)
|
|
118
|
+
return result.error;
|
|
119
|
+
return presentDeliberation(proposalId, result, { controlToolName: ctx.controlToolName });
|
|
181
120
|
}
|
|
182
121
|
export async function handleDaoControl(ctx, proposalId) {
|
|
183
|
-
const notReady = requireInitialized();
|
|
122
|
+
const notReady = requireInitialized(ctx.repository);
|
|
184
123
|
if (notReady)
|
|
185
124
|
return notReady;
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
return `Must be approved (current: ${proposal.status})`;
|
|
192
|
-
const result = runGates(proposal, state.config);
|
|
193
|
-
if (result.allGatesPassed) {
|
|
194
|
-
dispatchProposalEvent(proposal, { type: "CONTROL_PASS", result });
|
|
195
|
-
await recordAudit(proposal.id, "control", "gates_passed", "system", "All gates passed");
|
|
196
|
-
if (!state.deliveryPlans[proposal.id]) {
|
|
197
|
-
const plan = generateDeliveryPlan(proposal);
|
|
198
|
-
await storeDeliveryPlan(proposal.id, plan);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
if (ctx.failOnGateFailure) {
|
|
203
|
-
dispatchProposalEvent(proposal, { type: "CONTROL_FAIL" });
|
|
204
|
-
}
|
|
205
|
-
await recordAudit(proposal.id, "control", "gates_failed", "system", `${result.blockerCount} blockers`);
|
|
206
|
-
}
|
|
207
|
-
await saveState();
|
|
208
|
-
return formatControlResult(result);
|
|
125
|
+
const useCase = new ControlProposalUseCase({ repository: repositoryOrLegacy(ctx.repository), clock: systemClock });
|
|
126
|
+
const result = await useCase.execute({ proposalId, failOnGateFailure: ctx.failOnGateFailure });
|
|
127
|
+
if (!result.ok)
|
|
128
|
+
return result.error;
|
|
129
|
+
return presentControl(result.control);
|
|
209
130
|
}
|
|
210
|
-
export async function handleDaoExecute(proposalId) {
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return result.result;
|
|
131
|
+
export async function handleDaoExecute(ctx, proposalId) {
|
|
132
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
133
|
+
const projectConfig = await loadConfig(repository.get().daoRoot);
|
|
134
|
+
const workspace = createExecutionWorkspace(projectConfig.execution, ctx.adapter, ctx.workDir);
|
|
135
|
+
const useCase = new ExecuteProposalUseCase({ repository, clock: systemClock, workspace });
|
|
136
|
+
const result = await useCase.execute({ proposalId, actor: "user" });
|
|
137
|
+
if (!result.ok)
|
|
138
|
+
return result.error;
|
|
139
|
+
recordProposalExecuted(result.proposal.id, result.proposal.type);
|
|
140
|
+
return presentExecution(result);
|
|
221
141
|
}
|
|
222
142
|
export async function handleDaoShip(ctx, proposalId, options) {
|
|
223
|
-
const notReady = requireInitialized();
|
|
143
|
+
const notReady = requireInitialized(ctx.repository);
|
|
224
144
|
if (notReady)
|
|
225
145
|
return notReady;
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
}
|
|
146
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
147
|
+
// Shipping executes controlled proposals, so it must honour the same
|
|
148
|
+
// execution isolation as dao_execute — otherwise host shipping would
|
|
149
|
+
// bypass a configured worktree.
|
|
150
|
+
const projectConfig = await loadConfig(repository.get().daoRoot);
|
|
151
|
+
const workspace = createExecutionWorkspace(projectConfig.execution, ctx.adapter, ctx.workDir);
|
|
152
|
+
const useCase = new ShipProposalUseCase({ repository, clock: systemClock, workspace });
|
|
153
|
+
const result = await useCase.execute({
|
|
154
|
+
proposalId,
|
|
155
|
+
actor: ctx.adapter.hostId,
|
|
156
|
+
cascade: options?.cascade,
|
|
157
|
+
force: options?.force,
|
|
158
|
+
});
|
|
159
|
+
if (!result.ok)
|
|
160
|
+
return result.error;
|
|
161
|
+
for (const id of result.shipped) {
|
|
162
|
+
const proposal = repositoryOrLegacy(ctx.repository)
|
|
163
|
+
.get()
|
|
164
|
+
.proposals.find((candidate) => candidate.id === id);
|
|
165
|
+
if (proposal)
|
|
166
|
+
recordProposalExecuted(proposal.id, proposal.type);
|
|
279
167
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
168
|
+
return presentShip(result);
|
|
169
|
+
}
|
|
170
|
+
export async function handleDaoCheckEdit(ctx, paths) {
|
|
171
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
172
|
+
const notReady = requireInitialized(ctx.repository);
|
|
173
|
+
if (notReady)
|
|
174
|
+
return notReady;
|
|
175
|
+
const cleaned = [...new Set(paths.map((path) => path.trim()).filter(Boolean))];
|
|
176
|
+
// Refuse oversized requests outright: silently truncating could let a
|
|
177
|
+
// protected file ride just past the cutoff and come back as allowed.
|
|
178
|
+
if (cleaned.length > 200) {
|
|
179
|
+
return `Too many paths provided (${cleaned.length}). Pass at most 200 paths per edit check.`;
|
|
180
|
+
}
|
|
181
|
+
if (cleaned.length === 0)
|
|
182
|
+
return "No paths provided. Pass the files you are about to edit.";
|
|
183
|
+
const state = repository.get();
|
|
184
|
+
const projectConfig = await loadConfig(state.daoRoot);
|
|
185
|
+
const decision = evaluateEditGate({
|
|
186
|
+
paths: cleaned,
|
|
187
|
+
mode: projectConfig.mode,
|
|
188
|
+
criticalPaths: projectConfig.criticalPaths ?? [],
|
|
189
|
+
approved: state.proposals.map((proposal) => ({
|
|
190
|
+
proposalId: proposal.id,
|
|
191
|
+
affectedPaths: proposal.affectedPaths,
|
|
192
|
+
status: proposal.status,
|
|
193
|
+
})),
|
|
194
|
+
});
|
|
195
|
+
return formatEditGate(decision);
|
|
287
196
|
}
|
|
288
197
|
export async function handleDaoList() {
|
|
289
198
|
const notReady = requireInitialized();
|
|
@@ -335,117 +244,71 @@ export async function handleDaoArtefacts(proposalId) {
|
|
|
335
244
|
return `Proposal #${proposalId} not found.`;
|
|
336
245
|
return formatAllArtefacts(generateAllArtefacts(proposal));
|
|
337
246
|
}
|
|
338
|
-
export async function handleDaoDryRun(proposalId) {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
proposal.dryRunCanProceed = result.canProceed;
|
|
345
|
-
await saveState();
|
|
346
|
-
return formatDryRun(result);
|
|
247
|
+
export async function handleDaoDryRun(proposalId, repository) {
|
|
248
|
+
const result = await new DryRunProposalUseCase({
|
|
249
|
+
repository: repositoryOrLegacy(repository),
|
|
250
|
+
clock: systemClock,
|
|
251
|
+
}).execute({ proposalId });
|
|
252
|
+
return result.ok ? presentDryRun(result.analysis) : result.error;
|
|
347
253
|
}
|
|
348
|
-
export async function handleDaoRollback(proposalId) {
|
|
349
|
-
|
|
254
|
+
export async function handleDaoRollback(proposalId, repository) {
|
|
255
|
+
const result = await new RollbackProposalUseCase({ repository: repositoryOrLegacy(repository) }).execute({
|
|
256
|
+
proposalId,
|
|
257
|
+
});
|
|
258
|
+
return presentRollback(result);
|
|
350
259
|
}
|
|
351
|
-
export async function handleDaoDashboard() {
|
|
352
|
-
const notReady = requireInitialized();
|
|
260
|
+
export async function handleDaoDashboard(repository) {
|
|
261
|
+
const notReady = requireInitialized(repository);
|
|
353
262
|
if (notReady)
|
|
354
263
|
return notReady;
|
|
355
|
-
const state =
|
|
264
|
+
const state = repositoryOrLegacy(repository).get();
|
|
356
265
|
const dashboard = generateDashboard(state.proposals, state.outcomes, state.agents, state.healthSnapshots);
|
|
357
266
|
const health = computeHealthScore(state.proposals, state.outcomes, state.config.healthWeights);
|
|
358
267
|
return `${dashboard}\n\n${formatHealthScore(health)}`;
|
|
359
268
|
}
|
|
360
269
|
export async function handleDaoRoundtable(ctx) {
|
|
361
|
-
const notReady = requireInitialized();
|
|
270
|
+
const notReady = requireInitialized(ctx.repository);
|
|
362
271
|
if (notReady)
|
|
363
272
|
return notReady;
|
|
364
273
|
const state = getState();
|
|
365
274
|
const projectConfig = await loadConfig(state.daoRoot);
|
|
366
275
|
const agents = await loadAgentDefinitions(state.daoRoot, projectConfig);
|
|
367
|
-
const
|
|
276
|
+
const result = await new RoundTableUseCase({
|
|
277
|
+
repository: repositoryOrLegacy(ctx.repository),
|
|
278
|
+
worker: ctx.adapter,
|
|
279
|
+
clock: systemClock,
|
|
280
|
+
}).execute({
|
|
281
|
+
agents,
|
|
368
282
|
parentSessionModel: ctx.getSessionModel?.(),
|
|
369
283
|
hostDefaultModel: ctx.hostDefaultModel,
|
|
370
284
|
});
|
|
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);
|
|
285
|
+
return result.ok ? formatRoundTableResults(result.suggestions, result.proposalIds) : result.error;
|
|
409
286
|
}
|
|
410
287
|
export async function handleDaoAudit(proposalId) {
|
|
411
288
|
const entries = proposalId ? getAllAuditLog().filter((e) => e.proposalId === proposalId) : getAllAuditLog();
|
|
412
289
|
return formatAuditTrail(entries, proposalId);
|
|
413
290
|
}
|
|
414
|
-
export async function handleDaoRate(proposalId, score, comment) {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
await addRating(proposal.id, {
|
|
421
|
-
proposalId: proposal.id,
|
|
291
|
+
export async function handleDaoRate(proposalId, score, comment, repository) {
|
|
292
|
+
const result = await new RateProposalUseCase({
|
|
293
|
+
repository: repositoryOrLegacy(repository),
|
|
294
|
+
clock: systemClock,
|
|
295
|
+
}).execute({
|
|
296
|
+
proposalId,
|
|
422
297
|
rater: "user",
|
|
423
298
|
score,
|
|
424
299
|
comment,
|
|
425
|
-
ratedAt: new Date().toISOString(),
|
|
426
300
|
});
|
|
427
|
-
|
|
428
|
-
return `# ⭐ Rating Recorded — #${proposal.id}\n\n**Score:** ${score}/5\n**Comment:** ${comment}`;
|
|
301
|
+
return result.ok ? presentRating(result.rating) : result.error;
|
|
429
302
|
}
|
|
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.`;
|
|
303
|
+
export async function handleDaoUpdateProposal(proposalId, fields, repository) {
|
|
304
|
+
const result = await new UpdateProposalUseCase({ repository: repositoryOrLegacy(repository) }).execute({
|
|
305
|
+
proposalId,
|
|
306
|
+
fields,
|
|
307
|
+
});
|
|
308
|
+
return result.ok ? presentProposalUpdated(result.proposal) : result.error;
|
|
446
309
|
}
|
|
447
|
-
export async function handleDaoProposeAmendment(args) {
|
|
448
|
-
const notReady = requireInitialized();
|
|
310
|
+
export async function handleDaoProposeAmendment(args, repository) {
|
|
311
|
+
const notReady = requireInitialized(repository);
|
|
449
312
|
if (notReady)
|
|
450
313
|
return notReady;
|
|
451
314
|
let payload;
|
|
@@ -492,20 +355,16 @@ export async function handleDaoProposeAmendment(args) {
|
|
|
492
355
|
}
|
|
493
356
|
if (!payload)
|
|
494
357
|
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}\``;
|
|
358
|
+
const result = await new CreateAmendmentProposalUseCase({
|
|
359
|
+
repository: repositoryOrLegacy(repository),
|
|
360
|
+
clock: systemClock,
|
|
361
|
+
}).execute({ title: args.title, description: args.description, payload, proposedBy: "user" });
|
|
362
|
+
if (!result.ok)
|
|
363
|
+
return `❌ ${result.error}`;
|
|
364
|
+
return presentAmendment(result);
|
|
506
365
|
}
|
|
507
|
-
export async function handleDaoConfigGithub(
|
|
508
|
-
const state =
|
|
366
|
+
export async function handleDaoConfigGithub(ctx, args) {
|
|
367
|
+
const state = repositoryOrLegacy(ctx.repository).get();
|
|
509
368
|
await saveGitHubConfigToDaoRoot(state.daoRoot, args);
|
|
510
369
|
return [
|
|
511
370
|
`# GitHub Configured`,
|
|
@@ -517,14 +376,15 @@ export async function handleDaoConfigGithub(_ctx, args) {
|
|
|
517
376
|
"Available: `dao_github_create_branch`, `dao_github_open_pr`",
|
|
518
377
|
].join("\n");
|
|
519
378
|
}
|
|
520
|
-
export async function handleDaoGithubCreateBranch(
|
|
521
|
-
const
|
|
379
|
+
export async function handleDaoGithubCreateBranch(ctx, proposalId) {
|
|
380
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
381
|
+
const notReady = requireInitialized(ctx.repository);
|
|
522
382
|
if (notReady)
|
|
523
383
|
return notReady;
|
|
524
|
-
const proposal =
|
|
384
|
+
const proposal = repository.get().proposals.find((candidate) => candidate.id === proposalId);
|
|
525
385
|
if (!proposal)
|
|
526
386
|
return `Proposal #${proposalId} not found.`;
|
|
527
|
-
const configured = await loadGitHubConfigFromDaoRoot(
|
|
387
|
+
const configured = await loadGitHubConfigFromDaoRoot(repository.get().daoRoot);
|
|
528
388
|
if (!configured || !isGitHubEnabled()) {
|
|
529
389
|
return "GitHub not configured. Run `dao_config_github` with token, owner, and repo.";
|
|
530
390
|
}
|
|
@@ -534,16 +394,17 @@ export async function handleDaoGithubCreateBranch(_ctx, proposalId) {
|
|
|
534
394
|
return "Failed to create branch (GitHub API returned null)";
|
|
535
395
|
return `# Branch Created\n\n**Branch:** ${branchName}\n**SHA:** ${result.sha.slice(0, 7)}`;
|
|
536
396
|
}
|
|
537
|
-
export async function handleDaoGithubOpenPr(
|
|
538
|
-
const
|
|
397
|
+
export async function handleDaoGithubOpenPr(ctx, proposalId, headBranch) {
|
|
398
|
+
const repository = repositoryOrLegacy(ctx.repository);
|
|
399
|
+
const notReady = requireInitialized(ctx.repository);
|
|
539
400
|
if (notReady)
|
|
540
401
|
return notReady;
|
|
541
|
-
const proposal =
|
|
402
|
+
const proposal = repository.get().proposals.find((candidate) => candidate.id === proposalId);
|
|
542
403
|
if (!proposal)
|
|
543
404
|
return `Proposal #${proposalId} not found.`;
|
|
544
405
|
if (!headBranch)
|
|
545
406
|
return "headBranch is required";
|
|
546
|
-
const configured = await loadGitHubConfigFromDaoRoot(
|
|
407
|
+
const configured = await loadGitHubConfigFromDaoRoot(repository.get().daoRoot);
|
|
547
408
|
if (!configured || !isGitHubEnabled()) {
|
|
548
409
|
return "GitHub not configured. Run `dao_config_github` with token, owner, and repo.";
|
|
549
410
|
}
|