@b00dea/cockpit 0.0.0-stage → 0.1.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/CHANGELOG.md +375 -0
- package/LICENSE +21 -0
- package/README.md +22 -2
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2574 -0
- package/dist/autonomy.d.ts +44 -0
- package/dist/autonomy.js +156 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +62 -0
- package/dist/browser/commands.js +349 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +117 -0
- package/dist/browser/runtime.js +183 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +556 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +139 -0
- package/dist/cli-main.js +1405 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +113 -0
- package/dist/command-table.js +512 -0
- package/dist/config/load.d.ts +171 -0
- package/dist/config/load.js +345 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +335 -0
- package/dist/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +425 -0
- package/dist/environment/application/doctor.d.ts +89 -0
- package/dist/environment/application/doctor.js +235 -0
- package/dist/environment/application/guard.d.ts +43 -0
- package/dist/environment/application/guard.js +622 -0
- package/dist/environment/application/health.d.ts +134 -0
- package/dist/environment/application/health.js +379 -0
- package/dist/environment/application/lifecycle-context.d.ts +228 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +201 -0
- package/dist/environment/application/lifecycle.d.ts +17 -0
- package/dist/environment/application/lifecycle.js +729 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1709 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +117 -0
- package/dist/environment/compose-topology.js +413 -0
- package/dist/environment/contract.d.ts +489 -0
- package/dist/environment/contract.js +761 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +26 -0
- package/dist/environment/executable.js +167 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +189 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +276 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +484 -0
- package/dist/environment/generated-application/shared.js +349 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +389 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +699 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +109 -0
- package/dist/environment/git-observation.d.ts +183 -0
- package/dist/environment/git-observation.js +544 -0
- package/dist/environment/health-composition.d.ts +11 -0
- package/dist/environment/health-composition.js +628 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +308 -0
- package/dist/environment/init-application.js +697 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +29 -0
- package/dist/environment/lifecycle-composition.js +675 -0
- package/dist/environment/lifecycle-stage.d.ts +115 -0
- package/dist/environment/lifecycle-stage.js +398 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +344 -0
- package/dist/environment/operator-application.d.ts +50 -0
- package/dist/environment/operator-application.js +155 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/read-composition.d.ts +27 -0
- package/dist/environment/read-composition.js +352 -0
- package/dist/environment/readiness-composition.d.ts +38 -0
- package/dist/environment/readiness-composition.js +130 -0
- package/dist/environment/reclaim.d.ts +333 -0
- package/dist/environment/reclaim.js +1835 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +505 -0
- package/dist/environment/runtime.js +2335 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/state.d.ts +371 -0
- package/dist/environment/state.js +2013 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +96 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +102 -0
- package/dist/environment-exec/execute.js +1175 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +275 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/evaluator.d.ts +113 -0
- package/dist/guards/evaluator.js +1226 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +40 -0
- package/dist/guards/local-identity.js +123 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +175 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +40 -0
- package/dist/init/command.js +310 -0
- package/dist/init/derive.d.ts +51 -0
- package/dist/init/derive.js +715 -0
- package/dist/init/draft.d.ts +138 -0
- package/dist/init/draft.js +1205 -0
- package/dist/init/render.d.ts +35 -0
- package/dist/init/render.js +82 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1322 -0
- package/dist/schema.js +934 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +180 -0
- package/dist/surfaces/harness-registry.js +117 -0
- package/dist/surfaces/mcp.d.ts +95 -0
- package/dist/surfaces/mcp.js +186 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +681 -0
- package/dist/surfaces/render.d.ts +118 -0
- package/dist/surfaces/render.js +633 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +512 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/work-orders/application.d.ts +99 -0
- package/dist/work-orders/application.js +383 -0
- package/dist/work-orders/composition.d.ts +124 -0
- package/dist/work-orders/composition.js +1010 -0
- package/dist/work-orders/contract.d.ts +61 -0
- package/dist/work-orders/contract.js +122 -0
- package/dist/work-orders/store.d.ts +158 -0
- package/dist/work-orders/store.js +197 -0
- package/docs/README.md +65 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +50 -0
- package/docs/cli-reference.md +599 -0
- package/docs/command-list.md +51 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +171 -0
- package/docs/configuration-essentials.md +172 -0
- package/docs/configuration-reference.md +621 -0
- package/docs/environment.md +760 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +111 -0
- package/docs/getting-started.md +608 -0
- package/docs/harness-surfaces.md +433 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +419 -0
- package/docs/troubleshooting.md +361 -0
- package/docs/tutorial.md +170 -0
- package/docs/work-and-browser.md +254 -0
- package/libexec/browser-operation.cjs +186 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +74 -4
- package/surfaces/README.md +33 -0
- package/surfaces/agents/evaluator.agent.md +76 -0
- package/surfaces/guards/bash-guard.sh +48 -0
- package/surfaces/guards/claude.adapter.json +25 -0
- package/surfaces/guards/codex.adapter.json +24 -0
- package/surfaces/guards/opencode.adapter.json +25 -0
- package/surfaces/references/browser.md +63 -0
- package/surfaces/references/test-data-and-personas.md +84 -0
- package/surfaces/references/testing-tiers.md +11 -0
- package/surfaces/skills/cockpit-browser.skill.md +54 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +61 -0
- package/surfaces/skills/procedures/fix.md +81 -0
- package/surfaces/skills/procedures/setup.md +379 -0
- package/surfaces/skills/procedures/work.md +105 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { parse as parseToml, stringify as stringifyToml } from 'smol-toml';
|
|
3
|
+
import { parseDocument } from 'yaml';
|
|
4
|
+
import { SURFACE_TARGETS } from '../../surfaces/contract.js';
|
|
5
|
+
import { harnessFact, isGuardSurfaceTarget } from '../../surfaces/harness-registry.js';
|
|
6
|
+
import { RULESYNC_VERSION } from '../../surfaces/generator-adapter.js';
|
|
7
|
+
import { hasTargetMcpServers } from '../../surfaces/mcp.js';
|
|
8
|
+
import { codexWritableRoot, shippedInstructionCapabilities } from '../../surfaces/projection.js';
|
|
9
|
+
import { surfaceModelSha256 } from '../../surfaces/render.js';
|
|
10
|
+
import { GUARD_LOCAL_PATHS } from '../../guards/local-identity.js';
|
|
11
|
+
import { RefusalError, tryParseJson } from '../contract.js';
|
|
12
|
+
import { compareCodeUnits, ownRecord, sha256 } from './shared.js';
|
|
13
|
+
export function expectedSurfaceOutputs(tools, features, sources) {
|
|
14
|
+
const has = (feature) => features.includes(feature);
|
|
15
|
+
const hasFor = (target, feature) => has(feature)
|
|
16
|
+
&& harnessFact(target).rulesyncFeatures.some(candidate => candidate === feature);
|
|
17
|
+
const names = (prefix, suffix) => sources.filter(source => source.path.startsWith(prefix))
|
|
18
|
+
.map(source => source.path.slice(prefix.length, suffix.length === 0 ? undefined : -suffix.length));
|
|
19
|
+
const skills = sources.filter(source => source.path.startsWith('skills/')).map(source => source.path.slice('skills/'.length));
|
|
20
|
+
const permissionRulesForTarget = (target) => {
|
|
21
|
+
const permissionSource = sources.find(source => source.path === 'permissions.jsonc');
|
|
22
|
+
if (!permissionSource)
|
|
23
|
+
return false;
|
|
24
|
+
const source = ownRecord(JSON.parse(permissionSource.bytes));
|
|
25
|
+
const sections = [ownRecord(source?.permission), ownRecord(ownRecord(source?.[target])?.permission)];
|
|
26
|
+
return sections.some(permission => permission !== undefined && Object.values(permission).some(value => {
|
|
27
|
+
const rules = ownRecord(value);
|
|
28
|
+
return rules !== undefined && Object.keys(rules).length > 0;
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
const rows = Object.fromEntries(SURFACE_TARGETS.map(target => [target, []]));
|
|
32
|
+
if (has('rules'))
|
|
33
|
+
for (const target of SURFACE_TARGETS) {
|
|
34
|
+
if (!hasFor(target, 'rules'))
|
|
35
|
+
continue;
|
|
36
|
+
const root = harnessFact(target).outputs.instruction;
|
|
37
|
+
if (target === 'cursor')
|
|
38
|
+
rows[target].push(...names('rules/', '.md').map(name => `${root}/${name}.mdc`));
|
|
39
|
+
else
|
|
40
|
+
rows[target].push(root);
|
|
41
|
+
}
|
|
42
|
+
if (has('mcp'))
|
|
43
|
+
for (const target of SURFACE_TARGETS) {
|
|
44
|
+
if (hasFor(target, 'mcp') && hasTargetMcpServers(sources, target))
|
|
45
|
+
rows[target].push(harnessFact(target).outputs.mcp);
|
|
46
|
+
}
|
|
47
|
+
if (has('hooks'))
|
|
48
|
+
rows.claudecode.push('.claude/settings.json'), rows.codexcli.push('.codex/hooks.json'), rows.opencode.push('.opencode/plugins/rulesync-hooks.js');
|
|
49
|
+
if (has('hooks'))
|
|
50
|
+
rows.cursor.push('.cursor/hooks.json'), rows.grokcli.push('.grok/hooks/rulesync.json');
|
|
51
|
+
if (has('permissions'))
|
|
52
|
+
for (const target of SURFACE_TARGETS) {
|
|
53
|
+
if (!hasFor(target, 'permissions'))
|
|
54
|
+
continue;
|
|
55
|
+
if ((target !== 'codexcli' && target !== 'grokcli') || permissionRulesForTarget(target)) {
|
|
56
|
+
rows[target].push(...harnessFact(target).outputs.permissions);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (has('subagents'))
|
|
60
|
+
for (const name of names('subagents/', '.md')) {
|
|
61
|
+
rows.claudecode.push(`.claude/agents/${name}.md`);
|
|
62
|
+
rows.codexcli.push(`.codex/agents/${name}.toml`);
|
|
63
|
+
rows.opencode.push(`.opencode/agents/${name}.md`);
|
|
64
|
+
rows.cursor.push(`.cursor/agents/${name}.md`);
|
|
65
|
+
rows.grokcli.push(`.grok/agents/${name}.md`);
|
|
66
|
+
}
|
|
67
|
+
if (has('skills'))
|
|
68
|
+
for (const path of skills) {
|
|
69
|
+
rows.claudecode.push(`.claude/skills/${path}`);
|
|
70
|
+
rows.codexcli.push(`.agents/skills/${path}`);
|
|
71
|
+
const source = sources.find(candidate => candidate.path === `skills/${path}`);
|
|
72
|
+
if (path.endsWith('/SKILL.md') && source && expectsCodexSkillSidecar(source.bytes)) {
|
|
73
|
+
rows.codexcli.push(`.agents/skills/${path.slice(0, -'SKILL.md'.length)}agents/openai.yaml`);
|
|
74
|
+
}
|
|
75
|
+
rows.opencode.push(`.opencode/skills/${path}`);
|
|
76
|
+
rows.cursor.push(`.cursor/skills/${path}`);
|
|
77
|
+
rows.grokcli.push(`.grok/skills/${path}`);
|
|
78
|
+
}
|
|
79
|
+
return Object.fromEntries(tools.map(target => [target, [...new Set(rows[target])].sort(compareCodeUnits)]));
|
|
80
|
+
}
|
|
81
|
+
export function expectedClaudePluginOutputs(features, sources) {
|
|
82
|
+
const rows = [];
|
|
83
|
+
if (features.includes('mcp'))
|
|
84
|
+
rows.push('.mcp.json');
|
|
85
|
+
if (features.includes('hooks'))
|
|
86
|
+
rows.push('hooks/hooks.json');
|
|
87
|
+
if (features.includes('subagents'))
|
|
88
|
+
for (const source of sources.filter(row => row.path.startsWith('subagents/'))) {
|
|
89
|
+
rows.push(`agents/${source.path.slice('subagents/'.length)}`);
|
|
90
|
+
}
|
|
91
|
+
if (features.includes('skills'))
|
|
92
|
+
for (const source of sources.filter(row => row.path.startsWith('skills/'))) {
|
|
93
|
+
rows.push(source.path);
|
|
94
|
+
}
|
|
95
|
+
return [...new Set(rows)].sort(compareCodeUnits);
|
|
96
|
+
}
|
|
97
|
+
export function claudePluginManifest() {
|
|
98
|
+
const bytes = `${JSON.stringify({
|
|
99
|
+
name: 'cockpit-surfaces',
|
|
100
|
+
description: 'Generated cockpit agent surfaces.',
|
|
101
|
+
}, null, 2)}\n`;
|
|
102
|
+
return { bytes, sha256: sha256(bytes) };
|
|
103
|
+
}
|
|
104
|
+
// A rules overlay is written into the instruction file every harness loads at start, so Rulesync
|
|
105
|
+
// must see it as a root rule. A rule that already says `root: false` (Rulesync's default spelling)
|
|
106
|
+
// is still always loaded; one that narrows itself with `globs` cannot be, so it is refused by name
|
|
107
|
+
// rather than published as a rule that silently applies everywhere.
|
|
108
|
+
export function alwaysLoadedRule(bytes) {
|
|
109
|
+
if (!bytes.startsWith('---\n'))
|
|
110
|
+
return { kind: 'complete', bytes: `---\nroot: true\ntargets: ["*"]\n---\n${bytes}` };
|
|
111
|
+
const end = bytes.indexOf('\n---\n', 4);
|
|
112
|
+
if (end < 0)
|
|
113
|
+
return { kind: 'refusal', reason: 'opens a frontmatter block that never closes with a `---` line' };
|
|
114
|
+
const document = parseDocument(bytes.slice(4, end + 1), { uniqueKeys: true });
|
|
115
|
+
const frontmatter = document.errors.length === 0 ? document.toJS({ maxAliasCount: 0 }) : undefined;
|
|
116
|
+
if (!frontmatter || typeof frontmatter !== 'object' || Array.isArray(frontmatter)) {
|
|
117
|
+
return { kind: 'refusal', reason: 'has frontmatter that is not a YAML mapping' };
|
|
118
|
+
}
|
|
119
|
+
const { globs } = frontmatter;
|
|
120
|
+
if (globs !== undefined && !(Array.isArray(globs) && globs.every(glob => glob === '**/*' || glob === '**'))) {
|
|
121
|
+
return { kind: 'refusal', reason: 'limits itself to files with `globs`, but cockpit writes rules overlays into the instruction file every harness loads for every file' };
|
|
122
|
+
}
|
|
123
|
+
document.set('root', true);
|
|
124
|
+
if (!document.has('targets'))
|
|
125
|
+
document.set('targets', ['*']);
|
|
126
|
+
return { kind: 'complete', bytes: `---\n${document.toString()}---\n${bytes.slice(end + 5)}` };
|
|
127
|
+
}
|
|
128
|
+
function expectsCodexSkillSidecar(bytes) {
|
|
129
|
+
if (!bytes.startsWith('---\n'))
|
|
130
|
+
return false;
|
|
131
|
+
const end = bytes.indexOf('\n---\n', 4);
|
|
132
|
+
if (end < 0)
|
|
133
|
+
return false;
|
|
134
|
+
let frontmatter;
|
|
135
|
+
try {
|
|
136
|
+
const document = parseDocument(bytes.slice(4, end), { uniqueKeys: true });
|
|
137
|
+
if (document.errors.length > 0)
|
|
138
|
+
return false;
|
|
139
|
+
frontmatter = document.toJS({ maxAliasCount: 0 });
|
|
140
|
+
}
|
|
141
|
+
catch { /* unparseable input is malformed; the caller refuses it. */
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (!frontmatter || typeof frontmatter !== 'object' || Array.isArray(frontmatter))
|
|
145
|
+
return false;
|
|
146
|
+
const codexcli = frontmatter.codexcli;
|
|
147
|
+
if (!codexcli || typeof codexcli !== 'object' || Array.isArray(codexcli))
|
|
148
|
+
return false;
|
|
149
|
+
const metadata = codexcli;
|
|
150
|
+
const sections = ['interface', 'policy', 'dependencies'].map(key => metadata[key]);
|
|
151
|
+
const records = sections.filter((section) => section !== null && typeof section === 'object' && !Array.isArray(section));
|
|
152
|
+
return records.some(section => Object.keys(section).length > 0)
|
|
153
|
+
|| records.length > 0 && typeof metadata['short-description'] === 'string';
|
|
154
|
+
}
|
|
155
|
+
export function emptyGeneration() {
|
|
156
|
+
return {
|
|
157
|
+
kind: 'complete', status: 0, diagnostics: [],
|
|
158
|
+
mechanism: { package: 'rulesync', version: RULESYNC_VERSION, role: 'spelling' },
|
|
159
|
+
files: [],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Claude Code's native Read, Grep and Glob tools never reach the guard hook, so the read denial the
|
|
164
|
+
* hook applies to shell commands is restated as Claude `Read` deny rules for every declared
|
|
165
|
+
* instance, mounted or not: an instance is readable by the native tools whether or not a directory
|
|
166
|
+
* grant names its sibling, and an earlier rule set that followed grants left host-mounted and root
|
|
167
|
+
* instances readable. Siblings sit outside the project root, where neither `./`, `/..` nor `../`
|
|
168
|
+
* rules match and an absolute path would differ per clone, so each rule is anchored with `//**` on
|
|
169
|
+
* the sibling-relative suffix; an instance in the cockpit root itself is anchored at the project
|
|
170
|
+
* root with `/`. Measured on Claude Code 2.1.314, 2026-10-30, with an unruled control file beside
|
|
171
|
+
* them: `//**` rules refused Read and Grep of sibling instances and of nested `.secrets` files, and
|
|
172
|
+
* `/` rules refused root files, while the control stayed readable. Over-matching a deny is safe;
|
|
173
|
+
* glob metacharacters in a path become `?` so a literal bracket cannot narrow the rule.
|
|
174
|
+
*
|
|
175
|
+
* Every `.env` and `.env.*` file is denied too, as the guard denies it. Claude applies a deny before
|
|
176
|
+
* any allow, so these rules cannot carve out the documentation names the guard exempts: Claude's own
|
|
177
|
+
* tools refuse `.env.example` and declared templates as well, which a shell `cat` still reads.
|
|
178
|
+
*/
|
|
179
|
+
function claudeReadDenials(siblings, instances) {
|
|
180
|
+
const literal = (path) => path.replace(/[*?[\]\\!#()]/g, '?');
|
|
181
|
+
const rules = ['//**/.secrets/**', '//**/.env', '//**/.env.*', ...instanceReadPaths(siblings, instances)
|
|
182
|
+
.map(row => row.inRoot ? `/${literal(row.path)}` : `//**/${literal(row.path)}`)];
|
|
183
|
+
return [...new Set(rules)].sort(compareCodeUnits);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Each declared instance by the path that is the same in every clone: relative to the cockpit root
|
|
187
|
+
* for an instance there, otherwise the sibling-relative suffix with `..` and `.` segments dropped.
|
|
188
|
+
*/
|
|
189
|
+
function instanceReadPaths(siblings, instances) {
|
|
190
|
+
return instances.map(instance => {
|
|
191
|
+
const sibling = siblings.find(row => row.slug === instance.slug);
|
|
192
|
+
if (!sibling)
|
|
193
|
+
throw new RefusalError(`declared instance ${instance.path} names sibling ${instance.slug}, whose directory was not authenticated`);
|
|
194
|
+
if (sibling.path === '')
|
|
195
|
+
return { inRoot: true, path: instance.path };
|
|
196
|
+
const suffix = [...sibling.path.split('/'), ...instance.path.split('/')].filter(part => part !== '..' && part !== '.' && part !== '');
|
|
197
|
+
return { inRoot: false, path: suffix.join('/') };
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const OPENCODE_CONFIG_SCHEMA = 'https://opencode.ai/config.json';
|
|
201
|
+
/**
|
|
202
|
+
* OpenCode's native read tool asks its `read` permission with the file path relative to the Git
|
|
203
|
+
* worktree, and its `*` matches across `/`, so each protected path is denied both as written and
|
|
204
|
+
* below any prefix: that covers a cockpit root nested in a larger repository and siblings reached
|
|
205
|
+
* through `../`. Only `*` and `?` are pattern characters there; either one in a path becomes `?`,
|
|
206
|
+
* which over-matches a deny and so stays safe. The plugin's guard routing refuses the same reads,
|
|
207
|
+
* case-folded; these rules still deny the declared spellings when the plugin cannot load.
|
|
208
|
+
*/
|
|
209
|
+
export function openCodeReadDenials(siblings, instances) {
|
|
210
|
+
const literal = (path) => path.replace(/[*?]/g, '?');
|
|
211
|
+
const paths = ['.secrets/*', ...instanceReadPaths(siblings, instances).map(row => literal(row.path))];
|
|
212
|
+
return [...new Set(paths.flatMap(path => [path, `*/${path}`]))].sort(compareCodeUnits);
|
|
213
|
+
}
|
|
214
|
+
/** The machine-local file `sync` writes with a sibling's absolute directory, for OpenCode to read. */
|
|
215
|
+
export function openCodeGrantFile(slug) {
|
|
216
|
+
return `${GUARD_LOCAL_PATHS.directory}/opencode-grant-${slug}`;
|
|
217
|
+
}
|
|
218
|
+
// OpenCode matches `external_directory` patterns against absolute paths and has no token for the
|
|
219
|
+
// project root, so `../api/**` never matches (measured with OpenCode 1.19.4 on 2026-11-02). The
|
|
220
|
+
// committed pattern names a machine-local file instead; OpenCode substitutes `{file:...}` relative
|
|
221
|
+
// to the config file, and refuses to start, naming the file, while it is missing.
|
|
222
|
+
function openCodeExternalDirectories(grants) {
|
|
223
|
+
return Object.fromEntries([...new Set(grants.filter(grant => grant.target === 'opencode')
|
|
224
|
+
.map(grant => `{file:${openCodeGrantFile(grant.slug)}}/**`))].sort(compareCodeUnits).map(pattern => [pattern, 'allow']));
|
|
225
|
+
}
|
|
226
|
+
// The cockpit commands the shipped skills tell an agent to run and the guard admits without a
|
|
227
|
+
// prompt. Claude Code allows nothing in its default mode without a rule, so a headless session was
|
|
228
|
+
// denied even `test-run` from its own skill. A rule only lets Claude run the command without asking:
|
|
229
|
+
// the guard hook still runs first, and its ask or deny wins over the rule, so a command whose
|
|
230
|
+
// decider the [work.gates] or [autonomy] policy makes a person still asks. Commands that are always
|
|
231
|
+
// a person's (`init`, `sibling add`) and the destructive `down` are left out so they keep asking. Measured with Claude Code 2.1.316 on 2026-11-02 beside an unruled control: `Bash(<prefix> *)`
|
|
232
|
+
// ran a matching command headless, the control and a chain with an unmatched part were denied, a hook
|
|
233
|
+
// `ask` denied a matching command, and Claude ignores these rules until a person trusts the workspace.
|
|
234
|
+
const AGENT_COCKPIT_COMMANDS = [
|
|
235
|
+
'check *', 'doctor *', 'preflight *', 'logs *', 'sync *', 'reset * --apply', 'up *', 'sleep *', 'runtime measure *', 'test-run *',
|
|
236
|
+
'work status *', 'work accept *', 'work check *', 'work note *', 'work answer *', 'work grade *', 'work signoff *', 'work recover *',
|
|
237
|
+
'work verify *', 'grade *', 'upgrade *',
|
|
238
|
+
'browser drive *', 'browser screenshot *',
|
|
239
|
+
];
|
|
240
|
+
function claudeCommandAllowances() {
|
|
241
|
+
return Object.fromEntries(['npx --no cockpit', './node_modules/.bin/cockpit']
|
|
242
|
+
.flatMap(launcher => AGENT_COCKPIT_COMMANDS.map(command => [`${launcher} ${command}`, 'allow'])));
|
|
243
|
+
}
|
|
244
|
+
// What each harness loads at start, from the dated instruction-loading runs. Claude Code applies a
|
|
245
|
+
// scoped rule only to matching files, so a scoped source counts separately there.
|
|
246
|
+
export const GUIDE_LOAD_CHARACTERIZATIONS = Object.freeze(Object.fromEntries(shippedInstructionCapabilities()
|
|
247
|
+
.filter(fact => isGuardSurfaceTarget(fact.target))
|
|
248
|
+
.map(fact => [fact.target, {
|
|
249
|
+
measuredOn: fact.characterizedOn, metric: 'lines', scopeSemantics: fact.target === 'claudecode' ? 'conditional' : 'full',
|
|
250
|
+
provenance: fact.provenance,
|
|
251
|
+
}])));
|
|
252
|
+
export function nativeSources(mcp, grants, siblings, instances) {
|
|
253
|
+
const sources = [];
|
|
254
|
+
if (mcp.result.servers.length > 0) {
|
|
255
|
+
const transports = mcp.result.harnesses.flatMap(row => row.servers);
|
|
256
|
+
const servers = Object.fromEntries(mcp.result.servers.map(model => transports.find(server => server.name === model.name)).map(server => [server.name, {
|
|
257
|
+
type: 'stdio', command: server.command, args: server.args, disabled: !server.enabled,
|
|
258
|
+
}]));
|
|
259
|
+
const targets = Object.fromEntries(mcp.result.harnesses.flatMap(row => {
|
|
260
|
+
const removed = mcp.result.servers.filter(server => !row.servers.some(transport => transport.name === server.name));
|
|
261
|
+
return removed.length ? [[harnessFact(row.target).rulesyncTarget, {
|
|
262
|
+
mcpServers: Object.fromEntries(removed.map(server => [server.name, null])),
|
|
263
|
+
}]] : [];
|
|
264
|
+
}));
|
|
265
|
+
sources.push({ path: 'mcp.jsonc', bytes: `${JSON.stringify({ mcpServers: servers, ...targets }, null, 2)}\n` });
|
|
266
|
+
}
|
|
267
|
+
const paths = (target) => [...new Set(grants.filter(grant => grant.target === target).map(grant => grant.path))].sort(compareCodeUnits);
|
|
268
|
+
const claudeServers = mcp.result.harnesses.find(row => row.target === 'claudecode')?.servers ?? [];
|
|
269
|
+
const enabledMcpjsonServers = claudeServers.filter(server => server.enabled).map(server => server.name).sort();
|
|
270
|
+
// Claude Code ignores `disabled` in `.mcp.json` and offers an unlisted server for one-click
|
|
271
|
+
// approval; only this list keeps it off (measured with Claude Code 2.1.316 on 2026-11-02).
|
|
272
|
+
const disabledMcpjsonServers = claudeServers.filter(server => !server.enabled).map(server => server.name).sort();
|
|
273
|
+
sources.push({ path: 'permissions.jsonc', bytes: `${JSON.stringify({
|
|
274
|
+
permission: {},
|
|
275
|
+
claudecode: {
|
|
276
|
+
permission: {
|
|
277
|
+
read: Object.fromEntries(claudeReadDenials(siblings, instances).map(rule => [rule, 'deny'])),
|
|
278
|
+
bash: claudeCommandAllowances(),
|
|
279
|
+
},
|
|
280
|
+
permissions: { additionalDirectories: paths('claudecode') },
|
|
281
|
+
enabledMcpjsonServers,
|
|
282
|
+
...(disabledMcpjsonServers.length > 0 ? { disabledMcpjsonServers } : {}),
|
|
283
|
+
},
|
|
284
|
+
opencode: {
|
|
285
|
+
permission: { external_directory: openCodeExternalDirectories(grants) },
|
|
286
|
+
},
|
|
287
|
+
cursor: {
|
|
288
|
+
permission: {
|
|
289
|
+
read: Object.fromEntries(paths('cursor').map(path => [`${path}/**`, 'allow'])),
|
|
290
|
+
write: Object.fromEntries(paths('cursor').map(path => [`${path}/**`, 'allow'])),
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
grokcli: {
|
|
294
|
+
permission: {
|
|
295
|
+
read: Object.fromEntries(paths('grokcli').map(path => [`${path}/**`, 'allow'])),
|
|
296
|
+
edit: Object.fromEntries(paths('grokcli').map(path => [`${path}/**`, 'allow'])),
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
}, null, 2)}\n` });
|
|
300
|
+
return sources;
|
|
301
|
+
}
|
|
302
|
+
export function nativeFragmentSet(generated, model, paths) {
|
|
303
|
+
const modelSha256 = surfaceModelSha256(model);
|
|
304
|
+
if (!modelSha256)
|
|
305
|
+
return undefined;
|
|
306
|
+
const fragments = Object.entries(paths).map(([target, path]) => {
|
|
307
|
+
const row = generated.files.find(candidate => candidate.target === target && candidate.path === path);
|
|
308
|
+
return row ? { target: target, path, baseSha256: row.sha256, bytes: row.bytes, sha256: row.sha256 } : undefined;
|
|
309
|
+
});
|
|
310
|
+
if (fragments.some(fragment => fragment === undefined))
|
|
311
|
+
return undefined;
|
|
312
|
+
return { modelSha256, fragments: fragments };
|
|
313
|
+
}
|
|
314
|
+
export function nativeGrantFragmentSet(generated, grants, paths, openCodeReads) {
|
|
315
|
+
const modelSha256 = surfaceModelSha256(grants);
|
|
316
|
+
if (!modelSha256)
|
|
317
|
+
return undefined;
|
|
318
|
+
const fragments = Object.entries(paths).map(([target, path]) => {
|
|
319
|
+
const row = generated.files.find(candidate => candidate.target === target && candidate.path === path);
|
|
320
|
+
if (target !== 'opencode' && target !== 'codexcli') {
|
|
321
|
+
return row ? { target: target, path, baseSha256: row.sha256, bytes: row.bytes, sha256: row.sha256 } : undefined;
|
|
322
|
+
}
|
|
323
|
+
if (target === 'codexcli') {
|
|
324
|
+
let base = {};
|
|
325
|
+
if (row) {
|
|
326
|
+
try {
|
|
327
|
+
const parsed = ownRecord(parseToml(row.bytes));
|
|
328
|
+
if (!parsed)
|
|
329
|
+
return undefined;
|
|
330
|
+
base = parsed;
|
|
331
|
+
}
|
|
332
|
+
catch { /* unparseable input is malformed; the caller refuses it. */
|
|
333
|
+
return undefined;
|
|
334
|
+
}
|
|
335
|
+
if (['sandbox_mode', 'sandbox_workspace_write', 'default_permissions', 'permissions']
|
|
336
|
+
.some(key => Object.hasOwn(base, key)))
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
// Codex permission profiles reject the `..` segment required by a portable sibling
|
|
340
|
+
// grant. Publish the core-owned workspace-write settings alone: mixing the legacy
|
|
341
|
+
// sandbox with a generated profile would make Codex ignore that profile.
|
|
342
|
+
// Codex resolves a relative writable root against the directory of the config file,
|
|
343
|
+
// `.codex/`, not the cockpit root (measured with Codex 0.166.0 on 2026-11-02).
|
|
344
|
+
const writableRoots = [...new Set(grants.filter(grant => grant.target === target)
|
|
345
|
+
.map(grant => codexWritableRoot(grant.path)))].sort(compareCodeUnits);
|
|
346
|
+
const bytes = stringifyToml({ ...base, sandbox_mode: 'workspace-write', sandbox_workspace_write: { writable_roots: writableRoots } });
|
|
347
|
+
return { target: target, path, baseSha256: row?.sha256 ?? sha256(''), bytes, sha256: sha256(bytes) };
|
|
348
|
+
}
|
|
349
|
+
let base = {};
|
|
350
|
+
if (row) {
|
|
351
|
+
const parsed = ownRecord(tryParseJson(row.bytes));
|
|
352
|
+
if (!parsed)
|
|
353
|
+
return undefined;
|
|
354
|
+
base = parsed;
|
|
355
|
+
if (Object.hasOwn(base, 'permission'))
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
const externalDirectory = openCodeExternalDirectories(grants);
|
|
359
|
+
const read = Object.fromEntries(openCodeReads.map(rule => [rule, 'deny']));
|
|
360
|
+
// OpenCode writes `$schema` into a project config that lacks it at every start, which put an
|
|
361
|
+
// unowned member before the owned region; supplying OpenCode's exact value leaves it untouched.
|
|
362
|
+
const bytes = `${JSON.stringify({ $schema: OPENCODE_CONFIG_SCHEMA, ...base, permission: { external_directory: externalDirectory, read } }, null, 2)}\n`;
|
|
363
|
+
return { target: target, path, baseSha256: row?.sha256 ?? sha256(''), bytes, sha256: sha256(bytes) };
|
|
364
|
+
});
|
|
365
|
+
if (fragments.some(fragment => fragment === undefined))
|
|
366
|
+
return undefined;
|
|
367
|
+
return { modelSha256, fragments: fragments };
|
|
368
|
+
}
|
|
369
|
+
export function bindNativeGrantsToMcp(mcp, grants) {
|
|
370
|
+
const replacements = new Map();
|
|
371
|
+
for (const base of mcp.fragments) {
|
|
372
|
+
const grant = grants.fragments.find(fragment => fragment.target === base.target && fragment.path === base.path);
|
|
373
|
+
if (!grant)
|
|
374
|
+
continue;
|
|
375
|
+
if (grant.baseSha256 !== base.sha256)
|
|
376
|
+
return undefined;
|
|
377
|
+
replacements.set(`${base.target}\0${base.path}`, grant);
|
|
378
|
+
}
|
|
379
|
+
return { ...mcp, fragments: mcp.fragments.map(fragment => {
|
|
380
|
+
const grant = replacements.get(`${fragment.target}\0${fragment.path}`);
|
|
381
|
+
return grant ? { ...fragment, bytes: grant.bytes, sha256: grant.sha256 } : fragment;
|
|
382
|
+
}) };
|
|
383
|
+
}
|
|
384
|
+
export function nativeMcpPaths(targets) {
|
|
385
|
+
return Object.fromEntries(targets.map(target => [target, harnessFact(target).outputs.mcp]));
|
|
386
|
+
}
|
|
387
|
+
export function nativeGrantPaths(targets) {
|
|
388
|
+
return Object.fromEntries(targets.map(target => [target, harnessFact(target).outputs.permissions[0]]));
|
|
389
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type OwnershipManifest, type SurfacePriorOwnedEntry } from '../../surfaces/ownership.js';
|
|
2
|
+
import { type GeneratedEnvironmentCommandAdapters, type PreparedEnvironment, type RefusalOutcome } from './shared.js';
|
|
3
|
+
export declare function prepareSurfaces(prepared: PreparedEnvironment, priorOwned: readonly SurfacePriorOwnedEntry[], adapters: GeneratedEnvironmentCommandAdapters, manifest?: OwnershipManifest): Promise<PreparedEnvironment | RefusalOutcome>;
|