@heretek-ai/epistemic-swarm 0.7.25 → 1.0.2
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/index.ts +1 -0
- package/package.json +63 -139
- package/rpc.ts +1 -0
- package/server.ts +1 -0
- package/src/agents.ts +69 -0
- package/src/continue.ts +40 -0
- package/src/hooks.ts +283 -0
- package/src/panels.tsx +220 -0
- package/src/policy.ts +221 -0
- package/src/pr.ts +37 -0
- package/src/research.ts +63 -0
- package/src/rpc-def.ts +136 -0
- package/src/rpc.ts +331 -0
- package/src/runtime.ts +112 -0
- package/src/server.ts +311 -0
- package/src/session.ts +61 -0
- package/src/tools.ts +61 -0
- package/src/tui.tsx +206 -0
- package/tui.tsx +1 -0
- package/.agents/skills/brainstorming/SKILL.md +0 -19
- package/.agents/skills/code_audit/SKILL.md +0 -19
- package/.agents/skills/darkharvest/SKILL.md +0 -19
- package/.agents/skills/epistemic_search/SKILL.md +0 -19
- package/.agents/skills/factory/SKILL.md +0 -19
- package/.agents/skills/grilling/SKILL.md +0 -19
- package/.agents/skills/oss_scout/SKILL.md +0 -19
- package/.agents/skills/research_cache/SKILL.md +0 -19
- package/.agents/skills/swarm_config/SKILL.md +0 -19
- package/.claude-plugin/marketplace.json +0 -61
- package/.claude-plugin/plugin.json +0 -76
- package/.omp/README.md +0 -39
- package/.omp/SYSTEM.md +0 -17
- package/.omp/commands/audit.md +0 -10
- package/.omp/commands/brainstorming.md +0 -12
- package/.omp/commands/darkharvest.md +0 -11
- package/.omp/commands/domainexpansion.md +0 -9
- package/.omp/commands/factory.md +0 -9
- package/.omp/commands/grill.md +0 -9
- package/.omp/commands/scout.md +0 -10
- package/.omp/commands/swarm-config.md +0 -10
- package/.omp/commands/swarm.md +0 -9
- package/.omp/hooks/post/epistemic-audit.ts +0 -16
- package/.omp/hooks/pre/epistemic-redirect.ts +0 -21
- package/.omp/prompts/brainstorming.md +0 -8
- package/.omp/prompts/swarm.md +0 -8
- package/LICENSE +0 -126
- package/MARKETPLACE.md +0 -130
- package/README.md +0 -403
- package/bin/cli.js +0 -297
- package/config/claude-settings-patch.json +0 -10
- package/config/docker-compose.infra.yml +0 -23
- package/config/domain_packs/biopharma.json +0 -23
- package/config/domain_packs/legal.json +0 -19
- package/config/domain_packs/quant.json +0 -19
- package/config/mcp-research-servers.json +0 -33
- package/config/mcp_launcher.py +0 -153
- package/config/opencode-snippet.json +0 -156
- package/config/searxng_mcp.py +0 -92
- package/extensions/pi/index.js +0 -357
- package/hooks/hooks.json +0 -45
- package/install.sh +0 -473
- package/plugins/antigravity/README.md +0 -72
- package/plugins/antigravity/agents/alpha-thesis.md +0 -36
- package/plugins/antigravity/agents/beta-antithesis.md +0 -35
- package/plugins/antigravity/agents/brainstormer.md +0 -27
- package/plugins/antigravity/agents/code-auditor.md +0 -28
- package/plugins/antigravity/agents/darkharvester.md +0 -30
- package/plugins/antigravity/agents/epistemic-auditor.md +0 -28
- package/plugins/antigravity/agents/manager.md +0 -26
- package/plugins/antigravity/agents/oss-scout.md +0 -27
- package/plugins/antigravity/agents/programmer.md +0 -25
- package/plugins/antigravity/agents/qa-a.md +0 -22
- package/plugins/antigravity/agents/qa-b.md +0 -22
- package/plugins/antigravity/antigravity_hooks.py +0 -265
- package/plugins/antigravity/commands/audit.md +0 -11
- package/plugins/antigravity/commands/brainstorm.md +0 -9
- package/plugins/antigravity/commands/brainstorming.md +0 -10
- package/plugins/antigravity/commands/darkharvest.md +0 -12
- package/plugins/antigravity/commands/domainexpansion.md +0 -12
- package/plugins/antigravity/commands/factory.md +0 -14
- package/plugins/antigravity/commands/grill.md +0 -10
- package/plugins/antigravity/commands/scout.md +0 -11
- package/plugins/antigravity/commands/swarm-config.md +0 -9
- package/plugins/antigravity/commands/swarm.md +0 -12
- package/plugins/antigravity/hook_bus_bridge.js +0 -352
- package/plugins/antigravity/hooks.json +0 -44
- package/plugins/antigravity/mcp_config.json +0 -33
- package/plugins/antigravity/mcp_launcher.py +0 -58
- package/plugins/antigravity/plugin.json +0 -13
- package/plugins/antigravity/rules/AGENTS.md +0 -127
- package/plugins/antigravity/rules/epistemic-integrity.md +0 -16
- package/plugins/antigravity/skills/brainstorming/SKILL.md +0 -19
- package/plugins/antigravity/skills/code_audit/SKILL.md +0 -19
- package/plugins/antigravity/skills/darkharvest/SKILL.md +0 -19
- package/plugins/antigravity/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/antigravity/skills/factory/SKILL.md +0 -19
- package/plugins/antigravity/skills/grilling/SKILL.md +0 -19
- package/plugins/antigravity/skills/oss_scout/SKILL.md +0 -19
- package/plugins/antigravity/skills/research_cache/SKILL.md +0 -19
- package/plugins/antigravity/skills/swarm_config/SKILL.md +0 -19
- package/plugins/codex/AGENTS.md.snippet +0 -10
- package/plugins/codex/README.md +0 -37
- package/plugins/codex/config.toml.snippet +0 -28
- package/plugins/codex/openai.yaml +0 -24
- package/plugins/codex/skills/brainstorming/SKILL.md +0 -19
- package/plugins/codex/skills/code_audit/SKILL.md +0 -19
- package/plugins/codex/skills/darkharvest/SKILL.md +0 -19
- package/plugins/codex/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/codex/skills/factory/SKILL.md +0 -19
- package/plugins/codex/skills/grilling/SKILL.md +0 -19
- package/plugins/codex/skills/oss_scout/SKILL.md +0 -19
- package/plugins/codex/skills/research_cache/SKILL.md +0 -19
- package/plugins/codex/skills/swarm_config/SKILL.md +0 -19
- package/plugins/darkharvest/.claude-plugin/plugin.json +0 -15
- package/plugins/darkharvest/agents/harvest-proponent.md +0 -22
- package/plugins/darkharvest/agents/harvest-redteam.md +0 -20
- package/plugins/darkharvest/evals/teardown-verdict/graders/license-line.md +0 -6
- package/plugins/darkharvest/evals/teardown-verdict/graders/skill-fired.md +0 -5
- package/plugins/darkharvest/evals/teardown-verdict/prompt.md +0 -6
- package/plugins/darkharvest/skills/darkharvest/SKILL.md +0 -70
- package/plugins/darkharvest/skills/darkharvest/scripts/harvest.py +0 -289
- package/plugins/factory/.claude-plugin/plugin.json +0 -15
- package/plugins/factory/agents/factory-manager.md +0 -22
- package/plugins/factory/agents/programmer.md +0 -16
- package/plugins/factory/agents/qa-adversarial.md +0 -17
- package/plugins/factory/agents/qa-functional.md +0 -17
- package/plugins/factory/evals/gate-halt/graders/gates-first.md +0 -6
- package/plugins/factory/evals/gate-halt/graders/skill-fired.md +0 -5
- package/plugins/factory/evals/gate-halt/prompt.md +0 -6
- package/plugins/factory/skills/factory/SKILL.md +0 -61
- package/plugins/factory/skills/factory/scripts/factory.py +0 -300
- package/plugins/gemini/GEMINI.md +0 -16
- package/plugins/gemini/README.md +0 -20
- package/plugins/gemini/commands/audit.toml +0 -6
- package/plugins/gemini/commands/brainstorming.toml +0 -10
- package/plugins/gemini/commands/darkharvest.toml +0 -8
- package/plugins/gemini/commands/domainexpansion.toml +0 -7
- package/plugins/gemini/commands/factory.toml +0 -8
- package/plugins/gemini/commands/grill.toml +0 -6
- package/plugins/gemini/commands/scout.toml +0 -7
- package/plugins/gemini/commands/swarm-config.toml +0 -7
- package/plugins/gemini/commands/swarm.toml +0 -8
- package/plugins/gemini/gemini-extension.json +0 -38
- package/plugins/gemini/hooks/hooks.json +0 -11
- package/plugins/gemini/skills/brainstorming/SKILL.md +0 -19
- package/plugins/gemini/skills/code_audit/SKILL.md +0 -19
- package/plugins/gemini/skills/darkharvest/SKILL.md +0 -19
- package/plugins/gemini/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/gemini/skills/factory/SKILL.md +0 -19
- package/plugins/gemini/skills/grilling/SKILL.md +0 -19
- package/plugins/gemini/skills/oss_scout/SKILL.md +0 -19
- package/plugins/gemini/skills/research_cache/SKILL.md +0 -19
- package/plugins/gemini/skills/swarm_config/SKILL.md +0 -19
- package/plugins/opencode/analysis-bridge.js +0 -620
- package/plugins/opencode/config-io.js +0 -1651
- package/plugins/opencode/dep-health.js +0 -1039
- package/plugins/opencode/hook-bus.js +0 -496
- package/plugins/opencode/index.js +0 -2992
- package/plugins/opencode/tui.js +0 -1551
- package/plugins/opencode/weight-baseline.json +0 -16
- package/plugins/opencode/weight-signals.js +0 -769
- package/plugins/research-cache/.claude-plugin/plugin.json +0 -15
- package/plugins/research-cache/skills/research_cache/SKILL.md +0 -36
- package/plugins/research-cache/skills/research_cache/__init__.py +0 -0
- package/plugins/research-cache/skills/research_cache/hasher.py +0 -302
- package/plugins/socratic-grilling/.claude-plugin/plugin.json +0 -15
- package/plugins/socratic-grilling/skills/grilling/SKILL.md +0 -61
- package/plugins/socratic-grilling/skills/grilling/__init__.py +0 -0
- package/plugins/socratic-grilling/skills/grilling/socratic_tree.py +0 -363
- package/prompts/agent_alpha_thesis.md +0 -70
- package/prompts/agent_beta_antithesis.md +0 -78
- package/prompts/agent_brainstormer.md +0 -143
- package/prompts/agent_code_auditor.md +0 -88
- package/prompts/agent_darkharvest.md +0 -140
- package/prompts/agent_oss_scout.md +0 -78
- package/prompts/antigravity_repo_factcheck.md +0 -143
- package/prompts/base_epistemic_system.md +0 -50
- package/prompts/epistemic_auditor.md +0 -74
- package/prompts/orchestrator.md +0 -70
- package/runner/__init__.py +0 -0
- package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
- package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
- package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
- package/runner/__pycache__/darkharvest_claims.cpython-311.pyc +0 -0
- package/runner/__pycache__/errors.cpython-311.pyc +0 -0
- package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
- package/runner/__pycache__/path_safety.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
- package/runner/__pycache__/preflight.cpython-311.pyc +0 -0
- package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
- package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
- package/runner/__pycache__/retrieval_log.cpython-311.pyc +0 -0
- package/runner/__pycache__/schema_validate.cpython-311.pyc +0 -0
- package/runner/__pycache__/schemas.cpython-311.pyc +0 -0
- package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
- package/runner/antigravity_hooks.py +0 -265
- package/runner/auctioneer.py +0 -169
- package/runner/auditor_engine.py +0 -711
- package/runner/claim_store.py +0 -417
- package/runner/claim_witness.py +0 -412
- package/runner/darkharvest_claims.py +0 -358
- package/runner/errors.py +0 -51
- package/runner/living_dossiers.py +0 -395
- package/runner/mcp_protocol.py +0 -188
- package/runner/mcp_server.py +0 -1447
- package/runner/path_safety.py +0 -62
- package/runner/pcrb.py +0 -290
- package/runner/pcrb_verify.py +0 -267
- package/runner/preflight.py +0 -1011
- package/runner/refinement.py +0 -580
- package/runner/research_swarm.py +0 -1848
- package/runner/retrieval_log.py +0 -90
- package/runner/schema_validate.py +0 -193
- package/runner/schemas.py +0 -630
- package/runner/state_machine.py +0 -463
- package/runner/tests/__pycache__/test_analysis_bridge.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_antigravity_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_backends.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claude_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_config_schema.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_contract_tooling.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_darkharvest_audit.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_dep_health.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_dossier_contract.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_factory.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_frontier_concurrency.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_frontier_mirror_standalone.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_grounding.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_hardening_contract.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_hook_bus.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_manifest_concurrency.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_nk_hardening.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_v2_registrars.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_phase08_waiver_reopens.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_anomaly.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_provider.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_provider_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm_config.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_sweep_regressions.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_weight_signals.cpython-311.pyc +0 -0
- package/runner/tests/fixtures/auction_objective.json +0 -35
- package/runner/tests/fixtures/borderline_claims.json +0 -27
- package/runner/tests/fixtures/config_validation_cases.json +0 -276
- package/runner/tests/fixtures/ddg_anomaly_page.html +0 -176
- package/runner/tests/fixtures/ddg_results_page.html +0 -28
- package/runner/tests/fixtures/divergence_objectives.json +0 -31
- package/runner/tests/test_analysis_bridge.py +0 -450
- package/runner/tests/test_antigravity_plugin.py +0 -361
- package/runner/tests/test_auction_order.py +0 -173
- package/runner/tests/test_backends.py +0 -457
- package/runner/tests/test_bet1_spike.py +0 -95
- package/runner/tests/test_claim_store.py +0 -162
- package/runner/tests/test_claim_witness.py +0 -186
- package/runner/tests/test_claude_plugin.py +0 -170
- package/runner/tests/test_config_schema.py +0 -879
- package/runner/tests/test_contract_tooling.py +0 -312
- package/runner/tests/test_darkharvest_audit.py +0 -395
- package/runner/tests/test_dep_health.py +0 -595
- package/runner/tests/test_domain_packs.py +0 -217
- package/runner/tests/test_dossier_contract.py +0 -196
- package/runner/tests/test_factory.py +0 -258
- package/runner/tests/test_fleet_seam.py +0 -113
- package/runner/tests/test_frontier_concurrency.py +0 -288
- package/runner/tests/test_frontier_mirror_standalone.py +0 -156
- package/runner/tests/test_grounding.py +0 -183
- package/runner/tests/test_hardening_contract.py +0 -391
- package/runner/tests/test_hook_bus.py +0 -956
- package/runner/tests/test_living_dossiers.py +0 -204
- package/runner/tests/test_manifest_concurrency.py +0 -187
- package/runner/tests/test_mcp_server.py +0 -257
- package/runner/tests/test_nk_hardening.py +0 -1046
- package/runner/tests/test_opencode_ux.py +0 -2438
- package/runner/tests/test_opencode_v2_registrars.py +0 -2157
- package/runner/tests/test_pcrb.py +0 -240
- package/runner/tests/test_phase08_waiver_reopens.py +0 -539
- package/runner/tests/test_refinement.py +0 -255
- package/runner/tests/test_search_anomaly.py +0 -342
- package/runner/tests/test_search_provider.py +0 -1534
- package/runner/tests/test_search_provider_plugin.py +0 -401
- package/runner/tests/test_swarm.py +0 -444
- package/runner/tests/test_swarm_config.py +0 -520
- package/runner/tests/test_sweep_regressions.py +0 -453
- package/runner/tests/test_webcache.py +0 -271
- package/runner/tests/test_weight_signals.py +0 -401
- package/schemas/alpha_dossier.schema.json +0 -204
- package/schemas/audit_report.schema.json +0 -79
- package/schemas/beta_dossier.schema.json +0 -214
- package/schemas/config.schema.json +0 -311
- package/schemas/frontier.schema.json +0 -61
- package/schemas/manifest.schema.json +0 -49
- package/schemas/scope_manifest.schema.json +0 -47
- package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
- package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
- package/scripts/__pycache__/check_docs.cpython-311.pyc +0 -0
- package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
- package/scripts/__pycache__/gen_schemas.cpython-311.pyc +0 -0
- package/scripts/auction_experiment.py +0 -188
- package/scripts/bet1_advisory_spike.py +0 -442
- package/scripts/build_adapters.py +0 -417
- package/scripts/check_docs.py +0 -66
- package/scripts/divergence_experiment.py +0 -214
- package/scripts/gen_schemas.py +0 -69
- package/skills/brainstorming/SKILL.md +0 -106
- package/skills/brainstorming/__init__.py +0 -1
- package/skills/brainstorming/scripts/brainstorm.py +0 -201
- package/skills/code_audit/SKILL.md +0 -45
- package/skills/darkharvest/SKILL.md +0 -70
- package/skills/darkharvest/scripts/harvest.py +0 -289
- package/skills/epistemic_search/SKILL.md +0 -67
- package/skills/epistemic_search/__init__.py +0 -1
- package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
- package/skills/epistemic_search/scripts/fetch.py +0 -156
- package/skills/epistemic_search/scripts/search.py +0 -551
- package/skills/epistemic_search/scripts/webcache.py +0 -339
- package/skills/factory/SKILL.md +0 -61
- package/skills/factory/scripts/factory.py +0 -300
- package/skills/grilling/SKILL.md +0 -61
- package/skills/grilling/__init__.py +0 -0
- package/skills/grilling/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/grilling/__pycache__/socratic_tree.cpython-311.pyc +0 -0
- package/skills/grilling/socratic_tree.py +0 -363
- package/skills/oss_scout/SKILL.md +0 -49
- package/skills/research_cache/SKILL.md +0 -36
- package/skills/research_cache/__init__.py +0 -0
- package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
- package/skills/research_cache/hasher.py +0 -302
- package/skills/swarm_config/SKILL.md +0 -178
- package/skills/swarm_config/__init__.py +0 -35
- package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
- package/skills/swarm_config/configure.py +0 -1002
package/src/rpc.ts
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// Server side of the human-only channel. Each mutating method needs a token
|
|
2
|
+
// from a preview made in the last two minutes over the same subject, so the
|
|
3
|
+
// human confirms exactly what the dialog showed (no swap between preview and
|
|
4
|
+
// confirm).
|
|
5
|
+
import { randomBytes } from "node:crypto"
|
|
6
|
+
import {
|
|
7
|
+
type ApprovalStage,
|
|
8
|
+
approvalSubject,
|
|
9
|
+
capabilityLoss,
|
|
10
|
+
commandSetHash,
|
|
11
|
+
factoryLayout,
|
|
12
|
+
factorySummary,
|
|
13
|
+
type HookEngine,
|
|
14
|
+
hashJson,
|
|
15
|
+
installServer,
|
|
16
|
+
isTrusted,
|
|
17
|
+
loadGatesConfig,
|
|
18
|
+
readIdeas,
|
|
19
|
+
readPlan,
|
|
20
|
+
readResult,
|
|
21
|
+
readScores,
|
|
22
|
+
recordApproval,
|
|
23
|
+
recordConsent,
|
|
24
|
+
trustProject,
|
|
25
|
+
verifyControl,
|
|
26
|
+
writeJson,
|
|
27
|
+
} from "@heretek-ai/es-core"
|
|
28
|
+
import type { Runtime } from "./runtime.ts"
|
|
29
|
+
import { pendingApprovals } from "./tools.ts"
|
|
30
|
+
|
|
31
|
+
interface Ticket {
|
|
32
|
+
readonly kind: string
|
|
33
|
+
readonly subject: string
|
|
34
|
+
readonly expires: number
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const TTL_MS = 120_000
|
|
38
|
+
|
|
39
|
+
export function createRpcHandlers(runtime: Runtime, notify: () => Promise<void>, hooks?: HookEngine) {
|
|
40
|
+
const tickets = new Map<string, Ticket>()
|
|
41
|
+
const issue = (kind: string, subject: unknown) => {
|
|
42
|
+
const token = randomBytes(12).toString("hex")
|
|
43
|
+
tickets.set(token, { kind, subject: hashJson(subject), expires: Date.now() + TTL_MS })
|
|
44
|
+
return token
|
|
45
|
+
}
|
|
46
|
+
const redeem = (token: string, kind: string, subject: unknown) => {
|
|
47
|
+
const ticket = tickets.get(token)
|
|
48
|
+
tickets.delete(token)
|
|
49
|
+
if (!ticket || ticket.kind !== kind || ticket.expires < Date.now())
|
|
50
|
+
throw new Error("The confirmation expired or does not match; preview again.")
|
|
51
|
+
if (ticket.subject !== hashJson(subject))
|
|
52
|
+
throw new Error("What you confirmed changed since the preview; preview again.")
|
|
53
|
+
}
|
|
54
|
+
const refused = (context: any, error: unknown) =>
|
|
55
|
+
context.error("refused", error instanceof Error ? error.message : String(error), {
|
|
56
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
/** Everything a trust approval covers: gate commands and project hooks. */
|
|
60
|
+
const trustSubject = async () => {
|
|
61
|
+
const { config } = await loadGatesConfig(runtime.root)
|
|
62
|
+
const gates = await commandSetHash(runtime.root, config.commands)
|
|
63
|
+
await hooks?.reload()
|
|
64
|
+
const hookStatus = hooks?.status()
|
|
65
|
+
const hookHash = hookStatus?.projectHash ?? ""
|
|
66
|
+
return {
|
|
67
|
+
gates,
|
|
68
|
+
hooks: { hash: hookHash, lines: hookStatus?.projectLines ?? [] },
|
|
69
|
+
lines: [...gates.lines, ...(hookStatus?.projectLines ?? [])],
|
|
70
|
+
key: { gates: gates.hash, hooks: hookHash },
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
status: async () => {
|
|
76
|
+
const state = await runtime.factory.read()
|
|
77
|
+
return {
|
|
78
|
+
summary: factorySummary(state),
|
|
79
|
+
stage: state?.stage ?? "NONE",
|
|
80
|
+
pending: (await pendingApprovals(runtime.root)).map((item) => item.stage),
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
factoryState: async () => {
|
|
84
|
+
const state = await runtime.factory.read()
|
|
85
|
+
return {
|
|
86
|
+
stage: state?.stage ?? "NONE",
|
|
87
|
+
...(state?.runId ? { runId: state.runId } : {}),
|
|
88
|
+
...(state?.halt ? { halt: state.halt.reason } : {}),
|
|
89
|
+
...(state?.release?.prUrl ? { release: state.release.prUrl } : {}),
|
|
90
|
+
...(state?.activePhase ? { activePhase: state.activePhase } : {}),
|
|
91
|
+
spend: {
|
|
92
|
+
usd: state?.spend.usd ?? 0,
|
|
93
|
+
estimated: state?.spend.estimated ?? false,
|
|
94
|
+
...(state?.spendCeilingUSD ? { ceilingUSD: state.spendCeilingUSD } : {}),
|
|
95
|
+
},
|
|
96
|
+
phases: (state?.phases ?? []).map((phase) => ({
|
|
97
|
+
id: phase.id,
|
|
98
|
+
title: phase.title,
|
|
99
|
+
status: phase.status,
|
|
100
|
+
failures: phase.failures,
|
|
101
|
+
qa: Object.fromEntries(Object.entries(phase.qa).filter(([, verdict]) => verdict !== undefined)),
|
|
102
|
+
})),
|
|
103
|
+
pending: (await pendingApprovals(runtime.root)).map((item) => item.stage),
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
lspState: async () => {
|
|
107
|
+
const status = await runtime.lsp.status()
|
|
108
|
+
const settings = await runtime.lsp.settings()
|
|
109
|
+
const servers = []
|
|
110
|
+
for (const server of settings.servers) {
|
|
111
|
+
const command = await runtime.lsp.command(server, runtime.root)
|
|
112
|
+
servers.push({
|
|
113
|
+
id: server.id,
|
|
114
|
+
extensions: server.extensions,
|
|
115
|
+
available: Array.isArray(command),
|
|
116
|
+
command: Array.isArray(command) ? command.join(" ") : String((command as any)?.unavailable ?? "unavailable"),
|
|
117
|
+
running: status.running.filter((item) => item.id === server.id).length,
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
return { enabled: status.enabled, servers, diagnostics: status.diagnostics }
|
|
121
|
+
},
|
|
122
|
+
hooksState: async () => {
|
|
123
|
+
await hooks?.reload()
|
|
124
|
+
const status = hooks?.status()
|
|
125
|
+
return {
|
|
126
|
+
handlers: status?.handlers ?? 0,
|
|
127
|
+
projectHandlers: status?.projectHandlers ?? 0,
|
|
128
|
+
trusted: status?.trusted ?? true,
|
|
129
|
+
projectLines: status?.projectLines ?? [],
|
|
130
|
+
diagnostics: status?.diagnostics ?? [],
|
|
131
|
+
recent: hooks?.recent.slice(-10) ?? [],
|
|
132
|
+
loss: capabilityLoss(hooks?.list() ?? [], "opencode").map((item) => ({
|
|
133
|
+
source: item.source,
|
|
134
|
+
event: item.event,
|
|
135
|
+
handler: item.handler,
|
|
136
|
+
support: item.support,
|
|
137
|
+
reason: item.reason,
|
|
138
|
+
})),
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
brainstormState: async () => {
|
|
142
|
+
const plan = await readPlan(runtime.root).catch(() => undefined)
|
|
143
|
+
if (!plan) return { active: false }
|
|
144
|
+
const ideas = await readIdeas(runtime.root).catch(() => [])
|
|
145
|
+
const scores = await readScores(runtime.root).catch(() => [])
|
|
146
|
+
const result = await readResult(runtime.root).catch(() => undefined)
|
|
147
|
+
const survivors = ideas.filter((idea) => !idea.duplicateOf)
|
|
148
|
+
return {
|
|
149
|
+
active: true,
|
|
150
|
+
brief: plan.brief.idea,
|
|
151
|
+
lenses: plan.lenses,
|
|
152
|
+
ideas: survivors.length,
|
|
153
|
+
duplicates: ideas.length - survivors.length,
|
|
154
|
+
scored: scores.length,
|
|
155
|
+
coverage: Object.fromEntries(
|
|
156
|
+
plan.lenses.map((lens) => [lens, survivors.filter((idea) => idea.lens === lens).length]),
|
|
157
|
+
),
|
|
158
|
+
shortlist: (result?.shortlist ?? []).map((entry) => ({
|
|
159
|
+
id: entry.id,
|
|
160
|
+
total: entry.total,
|
|
161
|
+
outlier: entry.outlier,
|
|
162
|
+
title: result?.ideas.find((idea) => idea.id === entry.id)?.title ?? entry.id,
|
|
163
|
+
})),
|
|
164
|
+
gaps: result?.gaps ?? [],
|
|
165
|
+
complete: Boolean(result),
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
previewApproval: async (input: unknown) => {
|
|
169
|
+
const { stage } = input as { stage: ApprovalStage }
|
|
170
|
+
try {
|
|
171
|
+
const subject = await approvalSubject(runtime.root, stage)
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
title: `Approve ${stage}?`,
|
|
175
|
+
lines: [
|
|
176
|
+
...subject.summary,
|
|
177
|
+
"",
|
|
178
|
+
...subject.subject.map((item) => `${item.sha256.slice(0, 12)} ${item.path}`),
|
|
179
|
+
],
|
|
180
|
+
problems: [],
|
|
181
|
+
token: issue(`approve:${stage}`, subject.subject),
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
title: `Cannot approve ${stage}`,
|
|
187
|
+
lines: [],
|
|
188
|
+
problems: [error instanceof Error ? error.message : String(error)],
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
approve: async (input: unknown, context: any) => {
|
|
193
|
+
const { stage, user, token } = input as { stage: ApprovalStage; user: string; token: string }
|
|
194
|
+
try {
|
|
195
|
+
redeem(token, `approve:${stage}`, (await approvalSubject(runtime.root, stage)).subject)
|
|
196
|
+
const record = await recordApproval(runtime.root, {
|
|
197
|
+
stage,
|
|
198
|
+
channel: "tui",
|
|
199
|
+
approvedBy: user,
|
|
200
|
+
stateDir: runtime.stateDir,
|
|
201
|
+
})
|
|
202
|
+
await writeJson(
|
|
203
|
+
factoryLayout(runtime.root).pending,
|
|
204
|
+
(await pendingApprovals(runtime.root)).filter((item) => item.stage !== stage),
|
|
205
|
+
)
|
|
206
|
+
if (stage === "frontier") {
|
|
207
|
+
const state = await runtime.factory.read()
|
|
208
|
+
if (!state) await runtime.factory.begin(`human:${user}`)
|
|
209
|
+
if ((await runtime.factory.read())?.stage === "GRILL") await runtime.factory.beginResearch(`human:${user}`)
|
|
210
|
+
}
|
|
211
|
+
await notify()
|
|
212
|
+
return { message: `Approved ${stage} as ${record.approvedBy}.` }
|
|
213
|
+
} catch (error) {
|
|
214
|
+
return refused(context, error)
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
previewTrust: async () => {
|
|
218
|
+
const subject = await trustSubject()
|
|
219
|
+
const trusted =
|
|
220
|
+
(await isTrusted(runtime.root, subject.gates.hash, runtime.stateDir)) &&
|
|
221
|
+
(!subject.hooks.hash || (await isTrusted(runtime.root, subject.hooks.hash, runtime.stateDir, "hooks")))
|
|
222
|
+
return {
|
|
223
|
+
ok: subject.lines.length > 0,
|
|
224
|
+
title: trusted ? "Gate commands and hooks (already trusted)" : "Trust these gate commands and project hooks?",
|
|
225
|
+
lines: subject.lines.length ? subject.lines : ["No gate commands or project hooks detected."],
|
|
226
|
+
problems: [],
|
|
227
|
+
token: issue("trust", subject.key),
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
trust: async (input: unknown, context: any) => {
|
|
231
|
+
const { user, token } = input as { user: string; token: string }
|
|
232
|
+
try {
|
|
233
|
+
const subject = await trustSubject()
|
|
234
|
+
redeem(token, "trust", subject.key)
|
|
235
|
+
await trustProject(runtime.root, subject.gates.hash, subject.gates.lines, {
|
|
236
|
+
approvedBy: user,
|
|
237
|
+
stateDir: runtime.stateDir,
|
|
238
|
+
})
|
|
239
|
+
if (subject.hooks.hash)
|
|
240
|
+
await trustProject(runtime.root, subject.hooks.hash, subject.hooks.lines, {
|
|
241
|
+
approvedBy: user,
|
|
242
|
+
stateDir: runtime.stateDir,
|
|
243
|
+
kind: "hooks",
|
|
244
|
+
})
|
|
245
|
+
await hooks?.refresh()
|
|
246
|
+
return { message: `Trusted ${subject.lines.length} command/hook line(s).` }
|
|
247
|
+
} catch (error) {
|
|
248
|
+
return refused(context, error)
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
previewLspInstall: async (input: unknown) => {
|
|
252
|
+
const { id } = input as { id: string }
|
|
253
|
+
const server = (await runtime.lsp.settings()).servers.find((item) => item.id === id)
|
|
254
|
+
if (!server?.install)
|
|
255
|
+
return {
|
|
256
|
+
ok: false,
|
|
257
|
+
title: `Cannot install ${id}`,
|
|
258
|
+
lines: [],
|
|
259
|
+
problems: [server ? `${id} has no pinned install` : `unknown server ${id}`],
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
ok: true,
|
|
263
|
+
title: `Install ${id}?`,
|
|
264
|
+
lines: [
|
|
265
|
+
...server.install.packages.map((pkg) => `${pkg.name}@${pkg.version} ${pkg.integrity.slice(0, 32)}…`),
|
|
266
|
+
"Downloaded from npm, verified against the pinned sha512, installed with scripts disabled into your state dir.",
|
|
267
|
+
],
|
|
268
|
+
problems: [],
|
|
269
|
+
token: issue(`lsp:${id}`, server.install),
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
lspInstall: async (input: unknown, context: any) => {
|
|
273
|
+
const { id, user, token } = input as { id: string; user: string; token: string }
|
|
274
|
+
try {
|
|
275
|
+
const server = (await runtime.lsp.settings()).servers.find((item) => item.id === id)
|
|
276
|
+
if (!server?.install) throw new Error(`${id} has no pinned install`)
|
|
277
|
+
redeem(token, `lsp:${id}`, server.install)
|
|
278
|
+
await recordConsent(id, true, runtime.stateDir)
|
|
279
|
+
const bin = await installServer(server, { stateDir: runtime.stateDir })
|
|
280
|
+
return { message: `Installed ${id} (${bin}) for ${user}.` }
|
|
281
|
+
} catch (error) {
|
|
282
|
+
return refused(context, error)
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
previewResume: async () => {
|
|
286
|
+
const state = await runtime.factory.read()
|
|
287
|
+
if (state?.stage !== "HALTED")
|
|
288
|
+
return {
|
|
289
|
+
ok: false,
|
|
290
|
+
title: "Nothing to resume",
|
|
291
|
+
lines: [factorySummary(state)],
|
|
292
|
+
problems: ["The factory is not halted."],
|
|
293
|
+
}
|
|
294
|
+
const control = await verifyControl(runtime.root)
|
|
295
|
+
return {
|
|
296
|
+
ok: true,
|
|
297
|
+
title: "Resume the factory?",
|
|
298
|
+
lines: [
|
|
299
|
+
`Halted: ${state.halt?.reason}`,
|
|
300
|
+
`Spend: $${state.spend.usd.toFixed(2)} of $${state.spendCeilingUSD ?? "?"}`,
|
|
301
|
+
...(control.clean
|
|
302
|
+
? []
|
|
303
|
+
: ["Control-file drift (accepting it re-baselines):", ...control.violations.map((item) => ` ${item}`)]),
|
|
304
|
+
],
|
|
305
|
+
problems: [],
|
|
306
|
+
token: issue("resume", state.halt),
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
resume: async (input: unknown, context: any) => {
|
|
310
|
+
const { user, token, acceptControlDrift, raiseCeilingUSD, extendRuntime } = input as {
|
|
311
|
+
user: string
|
|
312
|
+
token: string
|
|
313
|
+
acceptControlDrift?: boolean
|
|
314
|
+
raiseCeilingUSD?: number
|
|
315
|
+
extendRuntime?: boolean
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
redeem(token, "resume", (await runtime.factory.read())?.halt)
|
|
319
|
+
const state = await runtime.factory.resume(user, {
|
|
320
|
+
...(acceptControlDrift ? { acceptControlDrift } : {}),
|
|
321
|
+
...(raiseCeilingUSD ? { raiseCeilingUSD } : {}),
|
|
322
|
+
...(extendRuntime ? { extendRuntime } : {}),
|
|
323
|
+
})
|
|
324
|
+
await notify()
|
|
325
|
+
return { message: `Resumed at ${state.stage}.` }
|
|
326
|
+
} catch (error) {
|
|
327
|
+
return refused(context, error)
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
}
|
|
331
|
+
}
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Per-location runtime shared by the plugin's hooks, tools, commands and RPC.
|
|
2
|
+
// Options are layered: the canonical config (global file → project file) with
|
|
3
|
+
// plugin options as the most specific override.
|
|
4
|
+
import {
|
|
5
|
+
stateDir as defaultStateDir,
|
|
6
|
+
type EsConfig,
|
|
7
|
+
Factory,
|
|
8
|
+
gateRunner,
|
|
9
|
+
LspManager,
|
|
10
|
+
loadEsConfig,
|
|
11
|
+
type PolicyContext,
|
|
12
|
+
} from "@heretek-ai/es-core"
|
|
13
|
+
import { ghPrOpener } from "./pr.ts"
|
|
14
|
+
|
|
15
|
+
/** Raw plugin options from opencode.json; every field is optional. */
|
|
16
|
+
export interface RawPluginOptions {
|
|
17
|
+
/** Override the user-global state dir (signing key, trust store). Tests only. */
|
|
18
|
+
readonly stateDir?: string
|
|
19
|
+
/** Model per tier, "provider/model". */
|
|
20
|
+
readonly models?: {
|
|
21
|
+
readonly fast?: string
|
|
22
|
+
readonly balanced?: string
|
|
23
|
+
readonly deep?: string
|
|
24
|
+
readonly agents?: Readonly<Record<string, string>>
|
|
25
|
+
}
|
|
26
|
+
readonly afterEdit?: "fast" | "off"
|
|
27
|
+
readonly estimate?: { readonly inputPerM?: number; readonly outputPerM?: number }
|
|
28
|
+
readonly pr?: "gh" | "off"
|
|
29
|
+
readonly lspAfterEdit?: boolean
|
|
30
|
+
readonly searchProvider?: "brave" | "firecrawl" | "searxng"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Resolved options: config defaults applied; consumers read this shape. */
|
|
34
|
+
export interface PluginOptions {
|
|
35
|
+
readonly stateDir?: string
|
|
36
|
+
readonly models?: EsConfig["models"]
|
|
37
|
+
readonly afterEdit: "fast" | "off"
|
|
38
|
+
readonly estimate?: { readonly inputPerM: number; readonly outputPerM: number }
|
|
39
|
+
readonly pr: "gh" | "off"
|
|
40
|
+
readonly lspAfterEdit: boolean
|
|
41
|
+
readonly searchProvider?: "brave" | "firecrawl" | "searxng"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Runtime {
|
|
45
|
+
readonly root: string
|
|
46
|
+
readonly options: PluginOptions
|
|
47
|
+
readonly config: EsConfig
|
|
48
|
+
/** Config files that contributed values, in layer order. */
|
|
49
|
+
readonly configSources: readonly string[]
|
|
50
|
+
readonly stateDir: string
|
|
51
|
+
readonly factory: Factory
|
|
52
|
+
readonly lsp: LspManager
|
|
53
|
+
policy(): Promise<PolicyContext>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function createRuntime(root: string, raw: RawPluginOptions): Promise<Runtime> {
|
|
57
|
+
// stateDir is runtime-only; everything else can come from config files.
|
|
58
|
+
const { stateDir: rawStateDir, ...overrides } = raw
|
|
59
|
+
const loaded = await loadEsConfig(root, { overrides })
|
|
60
|
+
const config = loaded.config
|
|
61
|
+
const options: PluginOptions = {
|
|
62
|
+
...(rawStateDir ? { stateDir: rawStateDir } : {}),
|
|
63
|
+
...(config.models ? { models: config.models } : {}),
|
|
64
|
+
afterEdit: config.afterEdit,
|
|
65
|
+
...(config.estimate ? { estimate: config.estimate } : {}),
|
|
66
|
+
pr: config.pr,
|
|
67
|
+
lspAfterEdit: config.lspAfterEdit,
|
|
68
|
+
...(config.searchProvider ? { searchProvider: config.searchProvider } : {}),
|
|
69
|
+
}
|
|
70
|
+
const stateDir = options.stateDir ?? defaultStateDir()
|
|
71
|
+
const lsp = new LspManager({ root, stateDir })
|
|
72
|
+
const factory = new Factory(root, {
|
|
73
|
+
gates: gateRunner({ stateDir }),
|
|
74
|
+
...(options.pr === "off" ? {} : { pr: ghPrOpener }),
|
|
75
|
+
stateDir,
|
|
76
|
+
})
|
|
77
|
+
return {
|
|
78
|
+
root,
|
|
79
|
+
options,
|
|
80
|
+
config,
|
|
81
|
+
configSources: loaded.sources,
|
|
82
|
+
stateDir,
|
|
83
|
+
factory,
|
|
84
|
+
lsp,
|
|
85
|
+
async policy() {
|
|
86
|
+
const worktree = await factory.activeWorktree().catch(() => undefined)
|
|
87
|
+
return { root, stateDir, ...(worktree ? { worktree } : {}) }
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Keep only the keys the user actually set, so config files are not clobbered. */
|
|
93
|
+
export function parseOptions(raw: Record<string, unknown> | undefined): RawPluginOptions {
|
|
94
|
+
const options = raw ?? {}
|
|
95
|
+
const models =
|
|
96
|
+
typeof options.models === "object" && options.models ? (options.models as RawPluginOptions["models"]) : undefined
|
|
97
|
+
const estimate =
|
|
98
|
+
typeof options.estimate === "object" && options.estimate
|
|
99
|
+
? (options.estimate as RawPluginOptions["estimate"])
|
|
100
|
+
: undefined
|
|
101
|
+
return {
|
|
102
|
+
...(typeof options.stateDir === "string" ? { stateDir: options.stateDir } : {}),
|
|
103
|
+
...(models ? { models } : {}),
|
|
104
|
+
...(options.afterEdit === "fast" || options.afterEdit === "off" ? { afterEdit: options.afterEdit } : {}),
|
|
105
|
+
...(estimate ? { estimate } : {}),
|
|
106
|
+
...(options.pr === "gh" || options.pr === "off" ? { pr: options.pr } : {}),
|
|
107
|
+
...(typeof options.lspAfterEdit === "boolean" ? { lspAfterEdit: options.lspAfterEdit } : {}),
|
|
108
|
+
...(typeof options.searchProvider === "string"
|
|
109
|
+
? { searchProvider: options.searchProvider as RawPluginOptions["searchProvider"] }
|
|
110
|
+
: {}),
|
|
111
|
+
}
|
|
112
|
+
}
|