@intentic/sandbox-contract 1.247.0 → 1.249.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/README.md +18 -15
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js.map +1 -1
- package/dist/chores/digest.d.ts.map +1 -1
- package/dist/chores/digest.js.map +1 -1
- package/dist/chores/extension-update.d.ts.map +1 -1
- package/dist/chores/extension-update.js.map +1 -1
- package/dist/chores/fix-deps.d.ts.map +1 -1
- package/dist/chores/fix-deps.js.map +1 -1
- package/dist/chores/index.d.ts +2 -2
- package/dist/chores/index.d.ts.map +1 -1
- package/dist/chores/index.js +1 -1
- package/dist/chores/index.js.map +1 -1
- package/dist/chores/probes.d.ts.map +1 -1
- package/dist/chores/probes.js.map +1 -1
- package/dist/chores/prompt.d.ts.map +1 -1
- package/dist/chores/prompt.js.map +1 -1
- package/dist/chores/stack.d.ts.map +1 -1
- package/dist/chores/stack.js.map +1 -1
- package/dist/chores/verdict.d.ts +7 -1
- package/dist/chores/verdict.d.ts.map +1 -1
- package/dist/chores/verdict.js +8 -0
- package/dist/chores/verdict.js.map +1 -1
- package/dist/contracts/accounts.contract.d.ts.map +1 -1
- package/dist/contracts/accounts.contract.js.map +1 -1
- package/dist/contracts/activity.contract.d.ts +1 -0
- package/dist/contracts/activity.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.d.ts +13 -205
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +2 -1
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +228 -54
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +11 -2
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/automations.contract.d.ts +35 -17
- package/dist/contracts/automations.contract.d.ts.map +1 -1
- package/dist/contracts/automations.contract.js +10 -1
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +0 -12
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/capabilities.contract.js +1 -1
- package/dist/contracts/capabilities.contract.js.map +1 -1
- package/dist/contracts/chores.contract.d.ts.map +1 -1
- package/dist/contracts/chores.contract.js.map +1 -1
- package/dist/contracts/ci.contract.d.ts +9 -0
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js.map +1 -1
- package/dist/contracts/exit.contract.d.ts.map +1 -1
- package/dist/contracts/exit.contract.js +1 -1
- package/dist/contracts/exit.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/git.contract.d.ts +45 -6
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +9 -9
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/host.contract.d.ts +2 -0
- package/dist/contracts/host.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.js.map +1 -1
- package/dist/contracts/intentic.contract.js +1 -1
- package/dist/contracts/intentic.contract.js.map +1 -1
- package/dist/contracts/logs.contract.d.ts.map +1 -1
- package/dist/contracts/logs.contract.js.map +1 -1
- package/dist/contracts/loops.contract.d.ts.map +1 -1
- package/dist/contracts/loops.contract.js.map +1 -1
- package/dist/contracts/personas.contract.d.ts +39 -4
- package/dist/contracts/personas.contract.d.ts.map +1 -1
- package/dist/contracts/personas.contract.js +10 -1
- package/dist/contracts/personas.contract.js.map +1 -1
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/providers.contract.js.map +1 -1
- package/dist/contracts/runner.contract.d.ts +6 -80
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.js +2 -2
- package/dist/contracts/runner.contract.js.map +1 -1
- package/dist/contracts/safety.contract.d.ts.map +1 -1
- package/dist/contracts/safety.contract.js +1 -1
- package/dist/contracts/safety.contract.js.map +1 -1
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/secrets.contract.js.map +1 -1
- package/dist/contracts/sessions.contract.d.ts +2 -41
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/sessions.contract.js +1 -1
- package/dist/contracts/sessions.contract.js.map +1 -1
- package/dist/contracts/settings.contract.d.ts +10 -10
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js.map +1 -1
- package/dist/contracts/share.contract.d.ts.map +1 -1
- package/dist/contracts/share.contract.js.map +1 -1
- package/dist/contracts/skills.contract.d.ts.map +1 -1
- package/dist/contracts/skills.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts +49 -73
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +12 -2
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/contracts/usage.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.js.map +1 -1
- package/dist/contracts/vpn.contract.d.ts.map +1 -1
- package/dist/contracts/vpn.contract.js +1 -1
- package/dist/contracts/vpn.contract.js.map +1 -1
- package/dist/contracts/webext.contract.d.ts.map +1 -1
- package/dist/contracts/webext.contract.js.map +1 -1
- package/dist/contracts/workflows.contract.d.ts +7 -6
- package/dist/contracts/workflows.contract.d.ts.map +1 -1
- package/dist/contracts/workflows.contract.js +12 -3
- package/dist/contracts/workflows.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/contracts/workspace.contract.js.map +1 -1
- package/dist/events/agent-events.d.ts +1237 -0
- package/dist/events/agent-events.d.ts.map +1 -0
- package/dist/events/agent-events.js +226 -0
- package/dist/events/agent-events.js.map +1 -0
- package/dist/events/cards.d.ts +404 -0
- package/dist/events/cards.d.ts.map +1 -0
- package/dist/events/cards.js +179 -0
- package/dist/events/cards.js.map +1 -0
- package/dist/events/resume.d.ts +23 -0
- package/dist/events/resume.d.ts.map +1 -0
- package/dist/events/resume.js +31 -0
- package/dist/events/resume.js.map +1 -0
- package/dist/events/system-events.d.ts +615 -0
- package/dist/events/system-events.d.ts.map +1 -0
- package/dist/events/system-events.js +64 -0
- package/dist/events/system-events.js.map +1 -0
- package/dist/events/transcript.d.ts +1755 -0
- package/dist/events/transcript.d.ts.map +1 -0
- package/dist/events/transcript.js +205 -0
- package/dist/events/transcript.js.map +1 -0
- package/dist/ids/conversation-ids.d.ts +8 -0
- package/dist/ids/conversation-ids.d.ts.map +1 -0
- package/dist/{conversation-ids.js → ids/conversation-ids.js} +13 -0
- package/dist/ids/conversation-ids.js.map +1 -0
- package/dist/ids/hostnames.d.ts.map +1 -0
- package/dist/ids/hostnames.js.map +1 -0
- package/dist/ids/session-names.d.ts.map +1 -0
- package/dist/ids/session-names.js.map +1 -0
- package/dist/ids/share-paths.d.ts.map +1 -0
- package/dist/ids/share-paths.js.map +1 -0
- package/dist/{tunnel-ids.d.ts → ids/tunnel-ids.d.ts} +1 -0
- package/dist/ids/tunnel-ids.d.ts.map +1 -0
- package/dist/{tunnel-ids.js → ids/tunnel-ids.js} +1 -0
- package/dist/ids/tunnel-ids.js.map +1 -0
- package/dist/index.d.ts +464 -447
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -47
- package/dist/index.js.map +1 -1
- package/dist/{agent-catalog.d.ts → models/agent-catalog.d.ts} +2 -2
- package/dist/models/agent-catalog.d.ts.map +1 -0
- package/dist/models/agent-catalog.js.map +1 -0
- package/dist/models/agent-runtimes.d.ts.map +1 -0
- package/dist/models/agent-runtimes.js.map +1 -0
- package/dist/{fast-tier.d.ts → models/fast-tier.d.ts} +1 -1
- package/dist/models/fast-tier.d.ts.map +1 -0
- package/dist/models/fast-tier.js.map +1 -0
- package/dist/models/model-order.d.ts.map +1 -0
- package/dist/models/model-order.js.map +1 -0
- package/dist/{model-pins.d.ts → models/model-pins.d.ts} +2 -4
- package/dist/models/model-pins.d.ts.map +1 -0
- package/dist/models/model-pins.js +22 -0
- package/dist/models/model-pins.js.map +1 -0
- package/dist/{model-roles.d.ts → models/model-roles.d.ts} +25 -30
- package/dist/models/model-roles.d.ts.map +1 -0
- package/dist/{model-roles.js → models/model-roles.js} +30 -27
- package/dist/models/model-roles.js.map +1 -0
- package/dist/{plan-pools.d.ts → models/plan-pools.d.ts} +1 -1
- package/dist/models/plan-pools.d.ts.map +1 -0
- package/dist/models/plan-pools.js.map +1 -0
- package/dist/models/prompt-complexity.d.ts.map +1 -0
- package/dist/models/prompt-complexity.js.map +1 -0
- package/dist/models/provider-specs.d.ts.map +1 -0
- package/dist/models/provider-specs.js.map +1 -0
- package/dist/policy/approvals-execution.d.ts.map +1 -0
- package/dist/policy/approvals-execution.js.map +1 -0
- package/dist/{batch-runs.d.ts → policy/batch-runs.d.ts} +5 -1
- package/dist/policy/batch-runs.d.ts.map +1 -0
- package/dist/{batch-runs.js → policy/batch-runs.js} +10 -7
- package/dist/policy/batch-runs.js.map +1 -0
- package/dist/policy/capability-env.d.ts.map +1 -0
- package/dist/policy/capability-env.js.map +1 -0
- package/dist/policy/capability-secrets.d.ts.map +1 -0
- package/dist/policy/capability-secrets.js.map +1 -0
- package/dist/{card-status.d.ts → policy/card-status.d.ts} +2 -2
- package/dist/policy/card-status.d.ts.map +1 -0
- package/dist/{card-status.js → policy/card-status.js} +1 -5
- package/dist/policy/card-status.js.map +1 -0
- package/dist/{command-classes.d.ts → policy/command-classes.d.ts} +6 -2
- package/dist/policy/command-classes.d.ts.map +1 -0
- package/dist/{command-classes.js → policy/command-classes.js} +48 -11
- package/dist/policy/command-classes.js.map +1 -0
- package/dist/{command-run.d.ts → policy/command-run.d.ts} +1 -1
- package/dist/policy/command-run.d.ts.map +1 -0
- package/dist/policy/command-run.js.map +1 -0
- package/dist/policy/control-scopes.d.ts +16 -0
- package/dist/policy/control-scopes.d.ts.map +1 -0
- package/dist/policy/control-scopes.js +26 -0
- package/dist/policy/control-scopes.js.map +1 -0
- package/dist/policy/credential-material.d.ts.map +1 -0
- package/dist/policy/credential-material.js.map +1 -0
- package/dist/policy/needs-action.d.ts.map +1 -0
- package/dist/policy/needs-action.js.map +1 -0
- package/dist/policy/output-fields.d.ts.map +1 -0
- package/dist/policy/output-fields.js.map +1 -0
- package/dist/policy/overlay-lint.d.ts.map +1 -0
- package/dist/policy/overlay-lint.js.map +1 -0
- package/dist/policy/owner-ticket.d.ts.map +1 -0
- package/dist/{owner-ticket.js → policy/owner-ticket.js} +1 -1
- package/dist/policy/owner-ticket.js.map +1 -0
- package/dist/{safety-policy.d.ts → policy/safety-policy.d.ts} +6 -5
- package/dist/policy/safety-policy.d.ts.map +1 -0
- package/dist/{safety-policy.js → policy/safety-policy.js} +12 -12
- package/dist/policy/safety-policy.js.map +1 -0
- package/dist/policy/search-globs.d.ts.map +1 -0
- package/dist/policy/search-globs.js.map +1 -0
- package/dist/protocol/container-requirements.d.ts +20 -0
- package/dist/protocol/container-requirements.d.ts.map +1 -0
- package/dist/protocol/container-requirements.js +23 -0
- package/dist/protocol/container-requirements.js.map +1 -0
- package/dist/{host-protocol.d.ts → protocol/host-protocol.d.ts} +1 -0
- package/dist/protocol/host-protocol.d.ts.map +1 -0
- package/dist/{host-protocol.js → protocol/host-protocol.js} +1 -0
- package/dist/protocol/host-protocol.js.map +1 -0
- package/dist/protocol/ingress-contract.d.ts.map +1 -0
- package/dist/{ingress-contract.js → protocol/ingress-contract.js} +1 -1
- package/dist/protocol/ingress-contract.js.map +1 -0
- package/dist/protocol/ingress-protocol.d.ts.map +1 -0
- package/dist/protocol/ingress-protocol.js.map +1 -0
- package/dist/protocol/listener-protocol.d.ts.map +1 -0
- package/dist/{listener-protocol.js → protocol/listener-protocol.js} +1 -1
- package/dist/protocol/listener-protocol.js.map +1 -0
- package/dist/{peer-dial.d.ts → protocol/peer-dial.d.ts} +4 -1
- package/dist/protocol/peer-dial.d.ts.map +1 -0
- package/dist/{peer-dial.js → protocol/peer-dial.js} +51 -10
- package/dist/protocol/peer-dial.js.map +1 -0
- package/dist/protocol/peer-mcp-server.d.ts.map +1 -0
- package/dist/protocol/peer-mcp-server.js.map +1 -0
- package/dist/protocol/request-id.d.ts.map +1 -0
- package/dist/protocol/request-id.js.map +1 -0
- package/dist/protocol/routes.d.ts.map +1 -0
- package/dist/protocol/routes.js.map +1 -0
- package/dist/{runner-protocol.d.ts → protocol/runner-protocol.d.ts} +1 -0
- package/dist/protocol/runner-protocol.d.ts.map +1 -0
- package/dist/{runner-protocol.js → protocol/runner-protocol.js} +2 -1
- package/dist/protocol/runner-protocol.js.map +1 -0
- package/dist/protocol/sse.d.ts.map +1 -0
- package/dist/protocol/sse.js.map +1 -0
- package/dist/{terminal-protocol.d.ts → protocol/terminal-protocol.d.ts} +1 -3
- package/dist/protocol/terminal-protocol.d.ts.map +1 -0
- package/dist/protocol/terminal-protocol.js.map +1 -0
- package/dist/protocol/webext-links.d.ts.map +1 -0
- package/dist/protocol/webext-links.js.map +1 -0
- package/dist/{webext-protocol.d.ts → protocol/webext-protocol.d.ts} +1 -0
- package/dist/protocol/webext-protocol.d.ts.map +1 -0
- package/dist/{webext-protocol.js → protocol/webext-protocol.js} +1 -0
- package/dist/protocol/webext-protocol.js.map +1 -0
- package/dist/schemas/activity.d.ts +2 -0
- package/dist/schemas/activity.d.ts.map +1 -1
- package/dist/schemas/activity.js +4 -0
- package/dist/schemas/activity.js.map +1 -1
- package/dist/schemas/agent.d.ts +17 -4
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +21 -4
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +17 -4
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +15 -4
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/approvals.d.ts.map +1 -1
- package/dist/schemas/approvals.js.map +1 -1
- package/dist/schemas/automations.d.ts +54 -28
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/automations.js +26 -8
- package/dist/schemas/automations.js.map +1 -1
- package/dist/schemas/capabilities.d.ts +0 -8
- package/dist/schemas/capabilities.d.ts.map +1 -1
- package/dist/schemas/capabilities.js +0 -4
- package/dist/schemas/capabilities.js.map +1 -1
- package/dist/schemas/ci.d.ts +10 -0
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +9 -1
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/codebase-health.d.ts.map +1 -1
- package/dist/schemas/codebase-health.js.map +1 -1
- package/dist/schemas/devices.d.ts +90 -0
- package/dist/schemas/devices.d.ts.map +1 -1
- package/dist/schemas/devices.js +10 -1
- package/dist/schemas/devices.js.map +1 -1
- package/dist/schemas/engines.d.ts.map +1 -1
- package/dist/schemas/engines.js.map +1 -1
- package/dist/schemas/environment.d.ts.map +1 -1
- package/dist/schemas/environment.js.map +1 -1
- package/dist/schemas/exit.d.ts.map +1 -1
- package/dist/schemas/exit.js.map +1 -1
- package/dist/schemas/extension-updates.d.ts.map +1 -1
- package/dist/schemas/extension-updates.js.map +1 -1
- package/dist/schemas/git-history.d.ts.map +1 -1
- package/dist/schemas/git-history.js.map +1 -1
- package/dist/schemas/git.d.ts +80 -16
- package/dist/schemas/git.d.ts.map +1 -1
- package/dist/schemas/git.js +37 -25
- package/dist/schemas/git.js.map +1 -1
- package/dist/schemas/history.d.ts.map +1 -1
- package/dist/schemas/history.js.map +1 -1
- package/dist/schemas/hosts.d.ts.map +1 -1
- package/dist/schemas/hosts.js.map +1 -1
- package/dist/schemas/inventory.d.ts.map +1 -1
- package/dist/schemas/inventory.js.map +1 -1
- package/dist/schemas/issues.d.ts +0 -1
- package/dist/schemas/issues.d.ts.map +1 -1
- package/dist/schemas/issues.js +0 -1
- package/dist/schemas/issues.js.map +1 -1
- package/dist/schemas/logs.d.ts.map +1 -1
- package/dist/schemas/logs.js.map +1 -1
- package/dist/schemas/loops.d.ts.map +1 -1
- package/dist/schemas/loops.js +1 -1
- package/dist/schemas/loops.js.map +1 -1
- package/dist/schemas/maintenance.d.ts.map +1 -1
- package/dist/schemas/maintenance.js.map +1 -1
- package/dist/schemas/marketplace.d.ts +0 -4
- package/dist/schemas/marketplace.d.ts.map +1 -1
- package/dist/schemas/panels.d.ts.map +1 -1
- package/dist/schemas/panels.js.map +1 -1
- package/dist/schemas/personas.d.ts +49 -4
- package/dist/schemas/personas.d.ts.map +1 -1
- package/dist/schemas/personas.js +32 -5
- package/dist/schemas/personas.js.map +1 -1
- package/dist/schemas/plan-limits.d.ts +2 -4
- package/dist/schemas/plan-limits.d.ts.map +1 -1
- package/dist/schemas/plan-limits.js +5 -8
- package/dist/schemas/plan-limits.js.map +1 -1
- package/dist/schemas/ports.d.ts.map +1 -1
- package/dist/schemas/ports.js.map +1 -1
- package/dist/schemas/provider-oauth.d.ts.map +1 -1
- package/dist/schemas/provider-oauth.js.map +1 -1
- package/dist/schemas/provider-subscriptions.d.ts +1 -1
- package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.js +1 -1
- package/dist/schemas/provider-subscriptions.js.map +1 -1
- package/dist/schemas/public.d.ts.map +1 -1
- package/dist/schemas/public.js.map +1 -1
- package/dist/schemas/push.d.ts.map +1 -1
- package/dist/schemas/push.js.map +1 -1
- package/dist/schemas/secrets.d.ts.map +1 -1
- package/dist/schemas/secrets.js.map +1 -1
- package/dist/schemas/settings.d.ts +7 -5
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +18 -8
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/share.d.ts.map +1 -1
- package/dist/schemas/share.js.map +1 -1
- package/dist/schemas/shared.d.ts +4 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/shared.js +3 -0
- package/dist/schemas/shared.js.map +1 -1
- package/dist/schemas/system.d.ts +6 -0
- package/dist/schemas/system.d.ts.map +1 -1
- package/dist/schemas/system.js +10 -0
- package/dist/schemas/system.js.map +1 -1
- package/dist/schemas/terminal.d.ts.map +1 -1
- package/dist/schemas/terminal.js.map +1 -1
- package/dist/schemas/usage.d.ts.map +1 -1
- package/dist/schemas/usage.js.map +1 -1
- package/dist/schemas/vpn.d.ts.map +1 -1
- package/dist/schemas/vpn.js.map +1 -1
- package/dist/schemas/webext.d.ts.map +1 -1
- package/dist/schemas/webext.js.map +1 -1
- package/dist/schemas/workflows.d.ts +66 -9
- package/dist/schemas/workflows.d.ts.map +1 -1
- package/dist/schemas/workflows.js +6 -5
- package/dist/schemas/workflows.js.map +1 -1
- package/dist/schemas/workspace-repos.d.ts.map +1 -1
- package/dist/schemas/workspace-repos.js.map +1 -1
- package/dist/schemas/workspace-search.d.ts.map +1 -1
- package/dist/schemas/workspace-search.js.map +1 -1
- package/dist/schemas/workspace-setup.d.ts.map +1 -1
- package/dist/schemas/workspace-setup.js.map +1 -1
- package/dist/schemas/workspace-tree.d.ts.map +1 -1
- package/dist/schemas/workspace-tree.js.map +1 -1
- package/dist/state/arrival.d.ts.map +1 -0
- package/dist/{arrival.js → state/arrival.js} +1 -1
- package/dist/state/arrival.js.map +1 -0
- package/dist/state/contract-lock.d.ts.map +1 -0
- package/dist/{contract-lock.js → state/contract-lock.js} +1 -1
- package/dist/state/contract-lock.js.map +1 -0
- package/dist/{definition.d.ts → state/definition.d.ts} +21 -17
- package/dist/state/definition.d.ts.map +1 -0
- package/dist/{definition.js → state/definition.js} +4 -4
- package/dist/state/definition.js.map +1 -0
- package/dist/state/history-state.d.ts.map +1 -0
- package/dist/{history-state.js → state/history-state.js} +1 -0
- package/dist/state/history-state.js.map +1 -0
- package/dist/state/runtime-state.d.ts.map +1 -0
- package/dist/state/runtime-state.js.map +1 -0
- package/dist/state/starter.d.ts.map +1 -0
- package/dist/state/starter.js.map +1 -0
- package/dist/state/state-portability.d.ts.map +1 -0
- package/dist/state/state-portability.js.map +1 -0
- package/dist/state/versions.d.ts.map +1 -0
- package/dist/state/versions.js.map +1 -0
- package/dist/{workspace-state.d.ts → state/workspace-state.d.ts} +8 -5
- package/dist/state/workspace-state.d.ts.map +1 -0
- package/dist/{workspace-state.js → state/workspace-state.js} +25 -1
- package/dist/state/workspace-state.js.map +1 -0
- package/dist/{documents.d.ts → text/documents.d.ts} +1 -1
- package/dist/text/documents.d.ts.map +1 -0
- package/dist/{documents.js → text/documents.js} +1 -1
- package/dist/text/documents.js.map +1 -0
- package/dist/text/embed.d.ts.map +1 -0
- package/dist/text/embed.js.map +1 -0
- package/dist/text/mentions.d.ts.map +1 -0
- package/dist/text/mentions.js.map +1 -0
- package/dist/text/model-answer.d.ts +3 -0
- package/dist/text/model-answer.d.ts.map +1 -0
- package/dist/text/model-answer.js +3 -0
- package/dist/text/model-answer.js.map +1 -0
- package/dist/text/path-refs.d.ts.map +1 -0
- package/dist/text/path-refs.js.map +1 -0
- package/dist/{shell-regions.d.ts → text/shell-regions.d.ts} +1 -1
- package/dist/text/shell-regions.d.ts.map +1 -0
- package/dist/text/shell-regions.js.map +1 -0
- package/dist/text/title.d.ts.map +1 -0
- package/dist/text/title.js.map +1 -0
- package/dist/{transcript-fold.d.ts → text/transcript-fold.d.ts} +2 -1
- package/dist/text/transcript-fold.d.ts.map +1 -0
- package/dist/{transcript-fold.js → text/transcript-fold.js} +2 -16
- package/dist/text/transcript-fold.js.map +1 -0
- package/dist/text/whisper.d.ts +3 -0
- package/dist/text/whisper.d.ts.map +1 -0
- package/dist/text/whisper.js +11 -0
- package/dist/text/whisper.js.map +1 -0
- package/dist/{workflow-faults.d.ts → text/workflow-faults.d.ts} +1 -1
- package/dist/text/workflow-faults.d.ts.map +1 -0
- package/dist/{workflow-faults.js → text/workflow-faults.js} +1 -1
- package/dist/text/workflow-faults.js.map +1 -0
- package/package.json +70 -70
- package/src/chores/chores.test.ts +4 -10
- package/src/chores/chores.ts +148 -392
- package/src/chores/digest.ts +8 -28
- package/src/chores/extension-update.ts +3 -8
- package/src/chores/fix-deps.ts +4 -18
- package/src/chores/index.ts +2 -2
- package/src/chores/probes.test.ts +7 -43
- package/src/chores/probes.ts +62 -167
- package/src/chores/prompt.ts +10 -34
- package/src/chores/stack.test.ts +6 -45
- package/src/chores/stack.ts +27 -118
- package/src/chores/verdict.test.ts +101 -80
- package/src/chores/verdict.ts +54 -99
- package/src/contracts/accounts.contract.ts +4 -19
- package/src/contracts/agent.contract.ts +7 -22
- package/src/contracts/agents.contract.ts +25 -71
- package/src/contracts/automations.contract.ts +14 -30
- package/src/contracts/capabilities.contract.ts +8 -35
- package/src/contracts/chores.contract.ts +4 -15
- package/src/contracts/endpoints.contract.ts +5 -22
- package/src/contracts/exit.contract.ts +7 -30
- package/src/contracts/extensions.contract.ts +8 -30
- package/src/contracts/git.contract.ts +25 -49
- package/src/contracts/host.contract.ts +9 -44
- package/src/contracts/intentic.contract.ts +1 -1
- package/src/contracts/logs.contract.ts +3 -13
- package/src/contracts/loops.contract.ts +9 -40
- package/src/contracts/personas.contract.ts +22 -30
- package/src/contracts/providers.contract.ts +4 -17
- package/src/contracts/runner.contract.ts +12 -39
- package/src/contracts/safety.contract.ts +5 -14
- package/src/contracts/secrets.contract.ts +4 -22
- package/src/contracts/sessions.contract.ts +1 -1
- package/src/contracts/settings.contract.ts +4 -10
- package/src/contracts/share.contract.ts +3 -9
- package/src/contracts/skills.contract.ts +4 -15
- package/src/contracts/system.contract.ts +26 -52
- package/src/contracts/usage.contract.ts +7 -21
- package/src/contracts/vpn.contract.ts +9 -16
- package/src/contracts/webext.contract.ts +9 -25
- package/src/contracts/workflows.contract.ts +34 -58
- package/src/contracts/workspace.contract.ts +19 -50
- package/src/events/agent-events.ts +345 -0
- package/src/events/cards.ts +286 -0
- package/src/{events.test.ts → events/resume.test.ts} +4 -19
- package/src/events/resume.ts +60 -0
- package/src/events/system-events.ts +139 -0
- package/src/events/transcript.ts +320 -0
- package/src/{conversation-ids.test.ts → ids/conversation-ids.test.ts} +25 -13
- package/src/ids/conversation-ids.ts +178 -0
- package/src/ids/hostnames.ts +129 -0
- package/src/ids/session-names.ts +29 -0
- package/src/ids/share-paths.ts +43 -0
- package/src/{tunnel-ids.test.ts → ids/tunnel-ids.test.ts} +1 -14
- package/src/ids/tunnel-ids.ts +29 -0
- package/src/index.ts +71 -88
- package/src/{agent-catalog.test.ts → models/agent-catalog.test.ts} +19 -93
- package/src/models/agent-catalog.ts +174 -0
- package/src/models/agent-runtimes.ts +201 -0
- package/src/models/capability-ledger.test.ts +84 -0
- package/src/{fast-tier.test.ts → models/fast-tier.test.ts} +7 -18
- package/src/models/fast-tier.ts +36 -0
- package/src/{model-order.test.ts → models/model-order.test.ts} +19 -40
- package/src/models/model-order.ts +163 -0
- package/src/models/model-pins.test.ts +87 -0
- package/src/models/model-pins.ts +57 -0
- package/src/models/model-roles.test.ts +38 -0
- package/src/models/model-roles.ts +180 -0
- package/src/{plan-pools.test.ts → models/plan-pools.test.ts} +6 -11
- package/src/models/plan-pools.ts +65 -0
- package/src/{prompt-complexity.test.ts → models/prompt-complexity.test.ts} +8 -60
- package/src/models/prompt-complexity.ts +215 -0
- package/src/{provider-specs.test.ts → models/provider-specs.test.ts} +18 -47
- package/src/models/provider-specs.ts +272 -0
- package/src/policy/approvals-execution.ts +58 -0
- package/src/{batch-runs.test.ts → policy/batch-runs.test.ts} +4 -20
- package/src/policy/batch-runs.ts +137 -0
- package/src/policy/capability-secrets.ts +5 -0
- package/src/{card-status.ts → policy/card-status.ts} +11 -26
- package/src/{command-classes.test.ts → policy/command-classes.test.ts} +11 -118
- package/src/policy/command-classes.ts +395 -0
- package/src/policy/command-run.ts +65 -0
- package/src/policy/control-scopes.ts +38 -0
- package/src/{credential-material.test.ts → policy/credential-material.test.ts} +4 -26
- package/src/policy/credential-material.ts +91 -0
- package/src/policy/needs-action.ts +5 -0
- package/src/policy/output-fields.ts +86 -0
- package/src/policy/overlay-lint.ts +100 -0
- package/src/{owner-ticket.test.ts → policy/owner-ticket.test.ts} +1 -1
- package/src/{owner-ticket.ts → policy/owner-ticket.ts} +9 -31
- package/src/policy/safety-policy.test.ts +84 -0
- package/src/policy/safety-policy.ts +142 -0
- package/src/policy/search-globs.ts +60 -0
- package/src/protocol/container-requirements.test.ts +72 -0
- package/src/protocol/container-requirements.ts +58 -0
- package/src/protocol/host-protocol.ts +29 -0
- package/src/protocol/ingress-contract.ts +103 -0
- package/src/{ingress-protocol.test.ts → protocol/ingress-protocol.test.ts} +25 -90
- package/src/protocol/ingress-protocol.ts +441 -0
- package/src/protocol/listener-protocol.ts +75 -0
- package/src/{peer-dial.test.ts → protocol/peer-dial.test.ts} +52 -1
- package/src/protocol/peer-dial.ts +207 -0
- package/src/{peer-mcp-server.ts → protocol/peer-mcp-server.ts} +16 -41
- package/src/protocol/request-id.ts +5 -0
- package/src/{routes.test.ts → protocol/routes.test.ts} +14 -22
- package/src/protocol/routes.ts +159 -0
- package/src/protocol/runner-protocol.ts +197 -0
- package/src/protocol/terminal-protocol.ts +13 -0
- package/src/protocol/webext-links.ts +50 -0
- package/src/protocol/webext-protocol.ts +24 -0
- package/src/schemas/activity.ts +22 -30
- package/src/schemas/agent.ts +130 -238
- package/src/schemas/agents.ts +165 -483
- package/src/schemas/approvals.ts +23 -71
- package/src/schemas/automations.ts +145 -249
- package/src/schemas/capabilities.ts +127 -414
- package/src/schemas/ci.ts +56 -108
- package/src/schemas/codebase-health.ts +7 -11
- package/src/schemas/devices.ts +98 -321
- package/src/schemas/engines.ts +16 -44
- package/src/schemas/environment.ts +41 -91
- package/src/schemas/exit.ts +24 -81
- package/src/schemas/extension-updates.ts +42 -87
- package/src/schemas/git-history.ts +30 -84
- package/src/schemas/git.ts +141 -256
- package/src/schemas/history.ts +14 -40
- package/src/schemas/hosts.ts +9 -15
- package/src/schemas/inventory.ts +8 -10
- package/src/schemas/issues.ts +66 -134
- package/src/schemas/logs.ts +15 -34
- package/src/schemas/loops.ts +46 -163
- package/src/schemas/maintenance.ts +47 -172
- package/src/schemas/panels.ts +20 -45
- package/src/schemas/personas.ts +85 -168
- package/src/schemas/plan-limits.ts +58 -197
- package/src/schemas/ports.ts +14 -32
- package/src/schemas/provider-oauth.ts +23 -76
- package/src/schemas/provider-subscriptions.ts +4 -13
- package/src/schemas/public.ts +4 -15
- package/src/schemas/push.ts +8 -36
- package/src/schemas/secrets.ts +20 -64
- package/src/schemas/settings.ts +177 -597
- package/src/schemas/share.ts +14 -32
- package/src/schemas/shared.ts +14 -13
- package/src/schemas/system.ts +46 -78
- package/src/schemas/terminal.ts +41 -120
- package/src/schemas/usage.ts +44 -233
- package/src/schemas/version-seam.test.ts +9 -26
- package/src/schemas/vpn.ts +27 -64
- package/src/schemas/webext.ts +22 -53
- package/src/schemas/workflows.ts +57 -183
- package/src/schemas/workspace-repos.ts +12 -24
- package/src/schemas/workspace-search.ts +17 -35
- package/src/schemas/workspace-setup.ts +4 -11
- package/src/schemas/workspace-tree.ts +32 -91
- package/src/state/arrival.ts +109 -0
- package/src/state/contract-lock.test.ts +17 -0
- package/src/state/contract-lock.ts +49 -0
- package/src/state/definition.ts +143 -0
- package/src/state/history-state.ts +103 -0
- package/src/{runtime-state.test.ts → state/runtime-state.test.ts} +3 -10
- package/src/state/runtime-state.ts +62 -0
- package/src/state/starter.ts +5 -0
- package/src/state/state-portability.ts +27 -0
- package/src/state/versions.ts +26 -0
- package/src/{workspace-state.test.ts → state/workspace-state.test.ts} +65 -173
- package/src/state/workspace-state.ts +669 -0
- package/src/{documents.test.ts → text/documents.test.ts} +1 -1
- package/src/text/documents.ts +42 -0
- package/src/text/embed.ts +132 -0
- package/src/text/mentions.ts +21 -0
- package/src/text/model-answer.ts +9 -0
- package/src/text/path-refs.ts +39 -0
- package/src/text/shell-regions.ts +224 -0
- package/src/{title.test.ts → text/title.test.ts} +13 -32
- package/src/text/title.ts +202 -0
- package/src/{transcript-fold.test.ts → text/transcript-fold.test.ts} +5 -83
- package/src/{transcript-fold.ts → text/transcript-fold.ts} +65 -170
- package/src/text/whisper.test.ts +19 -0
- package/src/text/whisper.ts +17 -0
- package/src/{workflow-faults.test.ts → text/workflow-faults.test.ts} +6 -24
- package/src/{workflow-faults.ts → text/workflow-faults.ts} +20 -60
- package/dist/agent-catalog.d.ts.map +0 -1
- package/dist/agent-catalog.js.map +0 -1
- package/dist/agent-runtimes.d.ts.map +0 -1
- package/dist/agent-runtimes.js.map +0 -1
- package/dist/approvals-execution.d.ts.map +0 -1
- package/dist/approvals-execution.js.map +0 -1
- package/dist/arrival.d.ts.map +0 -1
- package/dist/arrival.js.map +0 -1
- package/dist/batch-runs.d.ts.map +0 -1
- package/dist/batch-runs.js.map +0 -1
- package/dist/capability-env.d.ts.map +0 -1
- package/dist/capability-env.js.map +0 -1
- package/dist/capability-secrets.d.ts.map +0 -1
- package/dist/capability-secrets.js.map +0 -1
- package/dist/card-status.d.ts.map +0 -1
- package/dist/card-status.js.map +0 -1
- package/dist/command-classes.d.ts.map +0 -1
- package/dist/command-classes.js.map +0 -1
- package/dist/command-run.d.ts.map +0 -1
- package/dist/command-run.js.map +0 -1
- package/dist/contract-lock.d.ts.map +0 -1
- package/dist/contract-lock.js.map +0 -1
- package/dist/conversation-ids.d.ts +0 -4
- package/dist/conversation-ids.d.ts.map +0 -1
- package/dist/conversation-ids.js.map +0 -1
- package/dist/credential-material.d.ts.map +0 -1
- package/dist/credential-material.js.map +0 -1
- package/dist/definition.d.ts.map +0 -1
- package/dist/definition.js.map +0 -1
- package/dist/documents.d.ts.map +0 -1
- package/dist/documents.js.map +0 -1
- package/dist/embed.d.ts.map +0 -1
- package/dist/embed.js.map +0 -1
- package/dist/events.d.ts +0 -4336
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js +0 -725
- package/dist/events.js.map +0 -1
- package/dist/fast-tier.d.ts.map +0 -1
- package/dist/fast-tier.js.map +0 -1
- package/dist/history-state.d.ts.map +0 -1
- package/dist/history-state.js.map +0 -1
- package/dist/host-protocol.d.ts.map +0 -1
- package/dist/host-protocol.js.map +0 -1
- package/dist/hostnames.d.ts.map +0 -1
- package/dist/hostnames.js.map +0 -1
- package/dist/ingress-contract.d.ts.map +0 -1
- package/dist/ingress-contract.js.map +0 -1
- package/dist/ingress-protocol.d.ts.map +0 -1
- package/dist/ingress-protocol.js.map +0 -1
- package/dist/listener-protocol.d.ts.map +0 -1
- package/dist/listener-protocol.js.map +0 -1
- package/dist/mentions.d.ts.map +0 -1
- package/dist/mentions.js.map +0 -1
- package/dist/model-order.d.ts.map +0 -1
- package/dist/model-order.js.map +0 -1
- package/dist/model-pins.d.ts.map +0 -1
- package/dist/model-pins.js +0 -45
- package/dist/model-pins.js.map +0 -1
- package/dist/model-roles.d.ts.map +0 -1
- package/dist/model-roles.js.map +0 -1
- package/dist/needs-action.d.ts.map +0 -1
- package/dist/needs-action.js.map +0 -1
- package/dist/output-fields.d.ts.map +0 -1
- package/dist/output-fields.js.map +0 -1
- package/dist/overlay-lint.d.ts.map +0 -1
- package/dist/overlay-lint.js.map +0 -1
- package/dist/owner-ticket.d.ts.map +0 -1
- package/dist/owner-ticket.js.map +0 -1
- package/dist/path-refs.d.ts.map +0 -1
- package/dist/path-refs.js.map +0 -1
- package/dist/peer-dial.d.ts.map +0 -1
- package/dist/peer-dial.js.map +0 -1
- package/dist/peer-mcp-server.d.ts.map +0 -1
- package/dist/peer-mcp-server.js.map +0 -1
- package/dist/plan-pools.d.ts.map +0 -1
- package/dist/plan-pools.js.map +0 -1
- package/dist/prompt-complexity.d.ts.map +0 -1
- package/dist/prompt-complexity.js.map +0 -1
- package/dist/provider-specs.d.ts.map +0 -1
- package/dist/provider-specs.js.map +0 -1
- package/dist/request-id.d.ts.map +0 -1
- package/dist/request-id.js.map +0 -1
- package/dist/routes.d.ts.map +0 -1
- package/dist/routes.js.map +0 -1
- package/dist/runner-protocol.d.ts.map +0 -1
- package/dist/runner-protocol.js.map +0 -1
- package/dist/runtime-state.d.ts.map +0 -1
- package/dist/runtime-state.js.map +0 -1
- package/dist/safety-policy.d.ts.map +0 -1
- package/dist/safety-policy.js.map +0 -1
- package/dist/schemas/context.d.ts +0 -30
- package/dist/schemas/context.d.ts.map +0 -1
- package/dist/schemas/context.js +0 -34
- package/dist/schemas/context.js.map +0 -1
- package/dist/search-globs.d.ts.map +0 -1
- package/dist/search-globs.js.map +0 -1
- package/dist/session-names.d.ts.map +0 -1
- package/dist/session-names.js.map +0 -1
- package/dist/share-paths.d.ts.map +0 -1
- package/dist/share-paths.js.map +0 -1
- package/dist/shell-regions.d.ts.map +0 -1
- package/dist/shell-regions.js.map +0 -1
- package/dist/sse.d.ts.map +0 -1
- package/dist/sse.js.map +0 -1
- package/dist/starter.d.ts.map +0 -1
- package/dist/starter.js.map +0 -1
- package/dist/state-portability.d.ts.map +0 -1
- package/dist/state-portability.js.map +0 -1
- package/dist/terminal-protocol.d.ts.map +0 -1
- package/dist/terminal-protocol.js.map +0 -1
- package/dist/title.d.ts.map +0 -1
- package/dist/title.js.map +0 -1
- package/dist/transcript-fold.d.ts.map +0 -1
- package/dist/transcript-fold.js.map +0 -1
- package/dist/tunnel-ids.d.ts.map +0 -1
- package/dist/tunnel-ids.js.map +0 -1
- package/dist/versions.d.ts.map +0 -1
- package/dist/versions.js.map +0 -1
- package/dist/webext-links.d.ts.map +0 -1
- package/dist/webext-links.js.map +0 -1
- package/dist/webext-protocol.d.ts.map +0 -1
- package/dist/webext-protocol.js.map +0 -1
- package/dist/workflow-faults.d.ts.map +0 -1
- package/dist/workflow-faults.js.map +0 -1
- package/dist/workspace-state.d.ts.map +0 -1
- package/dist/workspace-state.js.map +0 -1
- package/src/agent-catalog.ts +0 -316
- package/src/agent-runtimes.ts +0 -419
- package/src/approvals-execution.ts +0 -96
- package/src/arrival.ts +0 -160
- package/src/batch-runs.ts +0 -188
- package/src/capability-ledger.test.ts +0 -140
- package/src/capability-secrets.ts +0 -20
- package/src/command-classes.ts +0 -617
- package/src/command-run.ts +0 -78
- package/src/contract-lock.test.ts +0 -23
- package/src/contract-lock.ts +0 -66
- package/src/conversation-ids.ts +0 -207
- package/src/credential-material.ts +0 -181
- package/src/definition.ts +0 -207
- package/src/documents.ts +0 -67
- package/src/embed.ts +0 -164
- package/src/events.ts +0 -1870
- package/src/fast-tier.ts +0 -72
- package/src/history-state.ts +0 -174
- package/src/host-protocol.ts +0 -36
- package/src/hostnames.ts +0 -180
- package/src/ingress-contract.ts +0 -157
- package/src/ingress-protocol.ts +0 -625
- package/src/listener-protocol.ts +0 -96
- package/src/mentions.ts +0 -25
- package/src/model-order.ts +0 -262
- package/src/model-pins.test.ts +0 -202
- package/src/model-pins.ts +0 -183
- package/src/model-roles.ts +0 -224
- package/src/needs-action.ts +0 -14
- package/src/output-fields.ts +0 -111
- package/src/overlay-lint.ts +0 -116
- package/src/path-refs.ts +0 -59
- package/src/peer-dial.ts +0 -163
- package/src/plan-pools.ts +0 -92
- package/src/prompt-complexity.ts +0 -334
- package/src/provider-specs.ts +0 -432
- package/src/request-id.ts +0 -41
- package/src/routes.ts +0 -219
- package/src/runner-protocol.ts +0 -239
- package/src/runtime-state.ts +0 -140
- package/src/safety-policy.test.ts +0 -88
- package/src/safety-policy.ts +0 -258
- package/src/schemas/context.ts +0 -87
- package/src/search-globs.ts +0 -76
- package/src/session-names.ts +0 -44
- package/src/share-paths.ts +0 -68
- package/src/shell-regions.ts +0 -289
- package/src/starter.ts +0 -13
- package/src/state-portability.ts +0 -56
- package/src/terminal-protocol.ts +0 -16
- package/src/title.ts +0 -267
- package/src/tunnel-ids.ts +0 -57
- package/src/versions.ts +0 -48
- package/src/webext-links.ts +0 -90
- package/src/webext-protocol.ts +0 -27
- package/src/workspace-state.ts +0 -1096
- /package/dist/{hostnames.d.ts → ids/hostnames.d.ts} +0 -0
- /package/dist/{hostnames.js → ids/hostnames.js} +0 -0
- /package/dist/{session-names.d.ts → ids/session-names.d.ts} +0 -0
- /package/dist/{session-names.js → ids/session-names.js} +0 -0
- /package/dist/{share-paths.d.ts → ids/share-paths.d.ts} +0 -0
- /package/dist/{share-paths.js → ids/share-paths.js} +0 -0
- /package/dist/{agent-catalog.js → models/agent-catalog.js} +0 -0
- /package/dist/{agent-runtimes.d.ts → models/agent-runtimes.d.ts} +0 -0
- /package/dist/{agent-runtimes.js → models/agent-runtimes.js} +0 -0
- /package/dist/{fast-tier.js → models/fast-tier.js} +0 -0
- /package/dist/{model-order.d.ts → models/model-order.d.ts} +0 -0
- /package/dist/{model-order.js → models/model-order.js} +0 -0
- /package/dist/{plan-pools.js → models/plan-pools.js} +0 -0
- /package/dist/{prompt-complexity.d.ts → models/prompt-complexity.d.ts} +0 -0
- /package/dist/{prompt-complexity.js → models/prompt-complexity.js} +0 -0
- /package/dist/{provider-specs.d.ts → models/provider-specs.d.ts} +0 -0
- /package/dist/{provider-specs.js → models/provider-specs.js} +0 -0
- /package/dist/{approvals-execution.d.ts → policy/approvals-execution.d.ts} +0 -0
- /package/dist/{approvals-execution.js → policy/approvals-execution.js} +0 -0
- /package/dist/{capability-env.d.ts → policy/capability-env.d.ts} +0 -0
- /package/dist/{capability-env.js → policy/capability-env.js} +0 -0
- /package/dist/{capability-secrets.d.ts → policy/capability-secrets.d.ts} +0 -0
- /package/dist/{capability-secrets.js → policy/capability-secrets.js} +0 -0
- /package/dist/{command-run.js → policy/command-run.js} +0 -0
- /package/dist/{credential-material.d.ts → policy/credential-material.d.ts} +0 -0
- /package/dist/{credential-material.js → policy/credential-material.js} +0 -0
- /package/dist/{needs-action.d.ts → policy/needs-action.d.ts} +0 -0
- /package/dist/{needs-action.js → policy/needs-action.js} +0 -0
- /package/dist/{output-fields.d.ts → policy/output-fields.d.ts} +0 -0
- /package/dist/{output-fields.js → policy/output-fields.js} +0 -0
- /package/dist/{overlay-lint.d.ts → policy/overlay-lint.d.ts} +0 -0
- /package/dist/{overlay-lint.js → policy/overlay-lint.js} +0 -0
- /package/dist/{owner-ticket.d.ts → policy/owner-ticket.d.ts} +0 -0
- /package/dist/{search-globs.d.ts → policy/search-globs.d.ts} +0 -0
- /package/dist/{search-globs.js → policy/search-globs.js} +0 -0
- /package/dist/{ingress-contract.d.ts → protocol/ingress-contract.d.ts} +0 -0
- /package/dist/{ingress-protocol.d.ts → protocol/ingress-protocol.d.ts} +0 -0
- /package/dist/{ingress-protocol.js → protocol/ingress-protocol.js} +0 -0
- /package/dist/{listener-protocol.d.ts → protocol/listener-protocol.d.ts} +0 -0
- /package/dist/{peer-mcp-server.d.ts → protocol/peer-mcp-server.d.ts} +0 -0
- /package/dist/{peer-mcp-server.js → protocol/peer-mcp-server.js} +0 -0
- /package/dist/{request-id.d.ts → protocol/request-id.d.ts} +0 -0
- /package/dist/{request-id.js → protocol/request-id.js} +0 -0
- /package/dist/{routes.d.ts → protocol/routes.d.ts} +0 -0
- /package/dist/{routes.js → protocol/routes.js} +0 -0
- /package/dist/{sse.d.ts → protocol/sse.d.ts} +0 -0
- /package/dist/{sse.js → protocol/sse.js} +0 -0
- /package/dist/{terminal-protocol.js → protocol/terminal-protocol.js} +0 -0
- /package/dist/{webext-links.d.ts → protocol/webext-links.d.ts} +0 -0
- /package/dist/{webext-links.js → protocol/webext-links.js} +0 -0
- /package/dist/{arrival.d.ts → state/arrival.d.ts} +0 -0
- /package/dist/{contract-lock.d.ts → state/contract-lock.d.ts} +0 -0
- /package/dist/{history-state.d.ts → state/history-state.d.ts} +0 -0
- /package/dist/{runtime-state.d.ts → state/runtime-state.d.ts} +0 -0
- /package/dist/{runtime-state.js → state/runtime-state.js} +0 -0
- /package/dist/{starter.d.ts → state/starter.d.ts} +0 -0
- /package/dist/{starter.js → state/starter.js} +0 -0
- /package/dist/{state-portability.d.ts → state/state-portability.d.ts} +0 -0
- /package/dist/{state-portability.js → state/state-portability.js} +0 -0
- /package/dist/{versions.d.ts → state/versions.d.ts} +0 -0
- /package/dist/{versions.js → state/versions.js} +0 -0
- /package/dist/{embed.d.ts → text/embed.d.ts} +0 -0
- /package/dist/{embed.js → text/embed.js} +0 -0
- /package/dist/{mentions.d.ts → text/mentions.d.ts} +0 -0
- /package/dist/{mentions.js → text/mentions.js} +0 -0
- /package/dist/{path-refs.d.ts → text/path-refs.d.ts} +0 -0
- /package/dist/{path-refs.js → text/path-refs.js} +0 -0
- /package/dist/{shell-regions.js → text/shell-regions.js} +0 -0
- /package/dist/{title.d.ts → text/title.d.ts} +0 -0
- /package/dist/{title.js → text/title.js} +0 -0
- /package/src/{hostnames.test.ts → ids/hostnames.test.ts} +0 -0
- /package/src/{share-paths.test.ts → ids/share-paths.test.ts} +0 -0
- /package/src/{capability-env.ts → policy/capability-env.ts} +0 -0
- /package/src/{overlay-lint.test.ts → policy/overlay-lint.test.ts} +0 -0
- /package/src/{search-globs.test.ts → policy/search-globs.test.ts} +0 -0
- /package/src/{ingress-contract.test.ts → protocol/ingress-contract.test.ts} +0 -0
- /package/src/{peer-mcp-server.test.ts → protocol/peer-mcp-server.test.ts} +0 -0
- /package/src/{sse.ts → protocol/sse.ts} +0 -0
- /package/src/{versions.test.ts → state/versions.test.ts} +0 -0
- /package/src/{embed.test.ts → text/embed.test.ts} +0 -0
- /package/src/{mentions.test.ts → text/mentions.test.ts} +0 -0
- /package/src/{path-refs.test.ts → text/path-refs.test.ts} +0 -0
package/src/workspace-state.ts
DELETED
|
@@ -1,1096 +0,0 @@
|
|
|
1
|
-
import { STATE_DIR } from "@intentic/constants";
|
|
2
|
-
import type { FileContribution } from "@intentic/extension-manifest";
|
|
3
|
-
import type { StateFile } from "./state-portability.js";
|
|
4
|
-
|
|
5
|
-
/* WHICH WORKSPACE FILE BACKS WHICH CORE VIEW, one declaration, read by both sides of the wire.
|
|
6
|
-
*
|
|
7
|
-
* The daemon's own state lives under `<workspace>/.intentic/`, the agent edits it out-of-band with its file
|
|
8
|
-
* tools, and the file watcher pushes every change as a `workspaceChanged` batch. Turning those paths back into
|
|
9
|
-
* "and therefore this view is stale" used to be a hand-written table in the BROWSER (web's systemEventRouting),
|
|
10
|
-
* maintained separately from the paths the daemon actually writes (composition.ts), two lists of the same
|
|
11
|
-
* fact, in two packages, with nothing tying them together.
|
|
12
|
-
*
|
|
13
|
-
* They drifted, exactly as that shape always does. The approvals queue is written by the AGENT (the approvals
|
|
14
|
-
* skill puts a file there) and rendered by the Approvals view, but it was never added to the browser's table,
|
|
15
|
-
* so a proposal appearing on disk while the owner watched the page changed nothing until they refocused the
|
|
16
|
-
* tab. Extension settings and the members list were missing for the same reason; writing them out is what
|
|
17
|
-
* showed that neither is an approvals-shaped hole, see their entries.
|
|
18
|
-
*
|
|
19
|
-
* So the binding is declared HERE, once, in the package both the daemon and the browser already import, and
|
|
20
|
-
* each side derives what it needs: the daemon builds its store paths from `path`, the browser builds its
|
|
21
|
-
* invalidation table from `invalidates`. Adding a manifest without saying what it makes stale is now a change
|
|
22
|
-
* to one visible list rather than an omission in a file nobody edits, and `workspace-state.test.ts` fails when
|
|
23
|
-
* a daemon store names a `.intentic` path this list doesn't carry.
|
|
24
|
-
*
|
|
25
|
-
* This mirrors what routes.ts does for the route surface ("nothing is generated and nothing is hand-maintained")
|
|
26
|
-
* one layer over: the same refusal to keep the same knowledge in two places.
|
|
27
|
-
*
|
|
28
|
-
* EXTENSIONS declare their own half in their manifest (`contributes.files`, @intentic/extension-api), in the same
|
|
29
|
-
* two fields, and the browser unions the two lists, see staleQueryKeys. That split is what this table is FOR:
|
|
30
|
-
* before it existed the core enumeration had to carry `automations` and `automation-approvals`, query keys owned
|
|
31
|
-
* by the automations extension, because the extension had no way to say so itself. A key belongs to whoever
|
|
32
|
-
* queries it. */
|
|
33
|
-
|
|
34
|
-
/* A core entry is an extension's `contributes.files` entry plus the two things only the core list needs: the
|
|
35
|
-
* right to declare NO invalidations (for a daemon-owned file, the answer more often than not), and a
|
|
36
|
-
* portability class, because the daemon's own state is what an environment export has to reason about.
|
|
37
|
-
*
|
|
38
|
-
* `path` is workspace-root-relative, forward-slash, the space `workspaceChanged` paths arrive in. Matching is
|
|
39
|
-
* by PREFIX, which lets one entry cover three shapes without a second matching rule:
|
|
40
|
-
* - an exact file `.intentic/config/settings.json`
|
|
41
|
-
* - a directory `.intentic/config/approvals/` (one file per approval)
|
|
42
|
-
* - a name family `.intentic/config/environment.custom.` (…Dockerfile and anything later named beside it)
|
|
43
|
-
* A directory entry keeps its trailing slash so it can never prefix-match a sibling file. Entries may NEST,
|
|
44
|
-
* see stateFileFor, which resolves the longest match rather than the first. */
|
|
45
|
-
export interface WorkspaceStateFile extends StateFile {
|
|
46
|
-
/* The browser query keys this file's contents feed. EMPTY is a real answer, not a gap, a file the browser
|
|
47
|
-
* renders nothing from, or one deliberately kept off the push path, and `why` says which. Never a prefix
|
|
48
|
-
* test over `.intentic/` as a whole: one stray write must not cost every view a refetch, which is the
|
|
49
|
-
* amplification that once turned an iq index rebuild into an endless request storm. */
|
|
50
|
-
readonly invalidates: readonly string[];
|
|
51
|
-
// Why this file has no invalidations, for the entries that declare none. Absent when it has some.
|
|
52
|
-
readonly why?: string;
|
|
53
|
-
/* Whether this entry is TRACKED by the root repo, the third thing an entry declares, and the one an owner
|
|
54
|
-
* sees most directly: a tracked entry gets a diff in the Changes review and a line in `git log`, so a change
|
|
55
|
-
* to how this sandbox behaves can be read, reverted, and attributed.
|
|
56
|
-
*
|
|
57
|
-
* ABSENT IS THE ANSWER FOR ALMOST EVERYTHING, and deliberately so. The root repo excludes `.intentic`
|
|
58
|
-
* wholesale and this flag is the only thing that carves an entry back out, so a store added later is
|
|
59
|
-
* untracked until someone says otherwise, the same default-deny the `portability` classes are built on, for
|
|
60
|
-
* the same reason. An ignore-pattern list would invert it: a credential store added next month would be
|
|
61
|
-
* committed on its first write, and nothing would have had to change for that to happen.
|
|
62
|
-
*
|
|
63
|
-
* WHAT EARNS IT is one question, asked of the entry rather than of its shape: does a change here change what
|
|
64
|
-
* this sandbox DOES? Two families answer yes.
|
|
65
|
-
* - CONFIGURATION, the small, slow-moving files that decide how the sandbox behaves: settings, personas,
|
|
66
|
-
* skills, automations, workflow designs, the environment overlay, which extensions are on.
|
|
67
|
-
* - AUTHORED CONTENT WHOSE CONSEQUENCES LEAVE THE SANDBOX, a workspace extension is code that runs in the
|
|
68
|
-
* app with a declared permission surface and a backend of its own; a post draft is words that go out
|
|
69
|
-
* under the owner's name. Neither is configuration, and reading `versioned` as config-only is what kept
|
|
70
|
-
* both of them out: an agent could write, and then run, a whole extension with a diff nowhere, and
|
|
71
|
-
* propose a public post that left no trace once declined. The rule was never "is this a setting", it was
|
|
72
|
-
* "can this be read, reverted and attributed", and for the two things the AGENT authors on its own,
|
|
73
|
-
* that matters more than it does for a file a person edited on purpose.
|
|
74
|
-
*
|
|
75
|
-
* Two kinds of entry stay out on purpose even though they are `carry` and hold no secret:
|
|
76
|
-
* - LEDGERS (workflow runs, loop iterations, thread bookkeeping, permission-usage batches, held-wake
|
|
77
|
-
* queues), which are rewritten on a timer or several times per step. Tracking them buries the owner's
|
|
78
|
-
* code review under machine noise, one of them is written every few seconds while a browser has the app
|
|
79
|
-
* open. A queue is a ledger too: it records that something was ASKED, and is emptied when it is answered.
|
|
80
|
-
* - BULK (session transcripts, artifacts), which are hundreds of megabytes of constantly-rewritten
|
|
81
|
-
* content. They travel in a bundle; they do not belong in a diff.
|
|
82
|
-
* `versioned` is therefore NARROWER than `carry`, and the two answer different questions: carry is "does it
|
|
83
|
-
* move to a new sandbox", this is "should a human review it changing". */
|
|
84
|
-
readonly versioned?: true;
|
|
85
|
-
/* AUTHORED but not configuration, the fourth question an entry can answer, and the narrowest: is this
|
|
86
|
-
* human- or agent-written TEXT that a workspace search should surface? Every `versioned` entry already is
|
|
87
|
-
* (a setting, a persona, a skill, things the agent is asked to find and edit), so this flag exists only
|
|
88
|
-
* for the entries that are authored content without being config: a draft awaiting approval, a staged
|
|
89
|
-
* README, an extension the agent wrote in place. Two of those three are now `versioned` as well, which makes
|
|
90
|
-
* the flag redundant to `SEARCHABLE_STATE_PATHS` on them and is why it stays anyway: searchability is a
|
|
91
|
-
* property of the content, and hanging it on `versioned` would mean a future decision to stop TRACKING a
|
|
92
|
-
* draft silently also stopped anyone FINDING one. Everything else under `.intentic` is machine state, and
|
|
93
|
-
* `SEARCHABLE_STATE_PATHS` below is what lets the search engine deny the rest BY DEFAULT instead of
|
|
94
|
-
* hand-keeping a deny list that goes stale the day a store is added (which is how a 98 kB loop ledger and
|
|
95
|
-
* whole third-party extension checkouts ended up ranking in code search). */
|
|
96
|
-
readonly authored?: true;
|
|
97
|
-
/* WHETHER DESKTOP-SYNC COPIES THIS DOWN, the fifth question, and the one `portability` cannot answer even
|
|
98
|
-
* though it looks like it should.
|
|
99
|
-
*
|
|
100
|
-
* Portability asks whether a piece of state may RESTORE into a different sandbox. Backup asks whether it may
|
|
101
|
-
* be COPIED to the owner's own machine so the loss of this sandbox is not the loss of the work. Those read as
|
|
102
|
-
* the same question and are not: `members.json` is the clearest case, and its own entry argues the half that
|
|
103
|
-
* was already written down, an access list that TRAVELLED would let a source sandbox hand itself the
|
|
104
|
-
* target's ownership, which is why it may never be `carry`. None of that reasoning says the owner may not
|
|
105
|
-
* hold a copy of who could drive their own sandbox. Conflating the two is what made the sync ignore the state
|
|
106
|
-
* dir wholesale, so a sandbox that went away took every persona, skill, draft and transcript with it.
|
|
107
|
-
*
|
|
108
|
-
* SO IT DERIVES, and this flag exists only to carve out the entry where the derivation is wrong. The default
|
|
109
|
-
* (backedUp below) is `carry` plus `identity`: ordinary state and the small records that bind this sandbox to
|
|
110
|
-
* its owner. `derived` is excluded for size, it is the caches, the checkouts and the browser profiles, all
|
|
111
|
-
* rebuildable and all bulk, and `secret` is excluded because a credential's exposure is the number of
|
|
112
|
-
* places it exists, and a laptop is one more place.
|
|
113
|
-
*
|
|
114
|
-
* `false` is the only value: an entry either accepts the derived answer or opts out of the copy, and there is
|
|
115
|
-
* no entry that needs opting IN against its class. Anything opting out says why on the entry. */
|
|
116
|
-
readonly backup?: false;
|
|
117
|
-
/* WHO BUILDS THIS TREE, when it is not the daemon, an extension, pnpm, another process entirely. Declared
|
|
118
|
-
* on the entry because the coverage guard's second direction ("every declared entry is built somewhere in
|
|
119
|
-
* the daemon") is only meaningful for entries the daemon owns: one it can never build must say who does, or
|
|
120
|
-
* the guard would read the entry as dead. Absent for everything the daemon writes itself. */
|
|
121
|
-
readonly outsideWriter?: string;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* Declared `as const` so the paths survive as literal types (see WorkspaceStatePath below), then published under
|
|
125
|
-
* the interface. Both bindings are needed and neither is redundant: the const is the only thing that can produce
|
|
126
|
-
* the path union, and every consumer reads entries as `WorkspaceStateFile`, an exact-literal tuple loses the
|
|
127
|
-
* optional members (`note`, `why`) on the entries that omit them, which is a worse type for reading than the
|
|
128
|
-
* interface it satisfies. One list, two views of it. */
|
|
129
|
-
const STATE_FILES = [
|
|
130
|
-
/* A capability add/remove recomposes the environment overlay and can add or drop a repo's panel.
|
|
131
|
-
*
|
|
132
|
-
* SPLIT ALREADY, and this entry's classification had not caught up, which is the whole of what changed here.
|
|
133
|
-
* It read `secret` on a claim that had stopped being true: that each entry's `config` carries that
|
|
134
|
-
* capability's credential, so the manifest is a secret in full. It does not. capabilities-store.ts's
|
|
135
|
-
* withSecretVault keeps credential VALUES off /work entirely, the manifest holds `__intentic_vaulted__`
|
|
136
|
-
* where one used to be, reads rehydrate so no caller noticed, and main.ts sweeps a hand-written value out at
|
|
137
|
-
* boot. What is left is the SHAPE of a connection: a kind, a URL, a username, a purpose, which permissions a
|
|
138
|
-
* connected device was granted.
|
|
139
|
-
*
|
|
140
|
-
* WHICH KEYS THOSE ARE IS DERIVED, not listed a second time: `echo` already answers "what of this config may
|
|
141
|
-
* a browser see", and the credential keys are exactly its complement (capabilities/secret-fields.ts). A kind
|
|
142
|
-
* that starts withholding a new field starts vaulting it on the same commit. That is what makes this
|
|
143
|
-
* classification a property of the code rather than a promise to re-audit it, the reason the entry can be
|
|
144
|
-
* reclassified at all, and the reason a hand-kept "these fields are safe" list could not have earned it.
|
|
145
|
-
*
|
|
146
|
-
* `carry`, and this is the entry where that earns the most. composeEnvironment reads its Dockerfile fragments
|
|
147
|
-
* from here, so a bundle that dropped it arrived on a stock overlay with an import report listing every
|
|
148
|
-
* connection to re-add by hand. It now arrives listing them itself, each visibly unconnected and waiting for
|
|
149
|
-
* one credential apiece, the shape personas.json has had all along, for the same reason.
|
|
150
|
-
*
|
|
151
|
-
* `versioned`, which is the point. Connecting this sandbox to a deployment orchestrator, or granting a
|
|
152
|
-
* connected device shell and screen control, is the largest change anyone makes to what it can DO, and it
|
|
153
|
-
* left a diff nowhere. One consequence worth stating rather than discovering: an identifier that pairs with a
|
|
154
|
-
* credential. Komodo's api key beside its api secret, which its own connector card calls "like a database
|
|
155
|
-
* user", is echoed, and therefore lands in the diff exactly as a database username would. */
|
|
156
|
-
{
|
|
157
|
-
path: ".intentic/config/capabilities.json",
|
|
158
|
-
invalidates: ["capabilities", "environment", "panels", "manifests"],
|
|
159
|
-
portability: "carry",
|
|
160
|
-
versioned: true,
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
/* Which workspace-derived recommendations the owner has said "not needed" to, and the evidence each was
|
|
164
|
-
* declined against. It rides the `capabilities` key because the catalog is what changes when one lands, and
|
|
165
|
-
* it travels because a decision about what this workspace does NOT need is as much the owner's as the
|
|
166
|
-
* connections themselves, an export that dropped it would greet them on the target with the same
|
|
167
|
-
* suggestions they had already dismissed. Holds no credential: it is a card name and a file path. */
|
|
168
|
-
{ path: ".intentic/config/capability-dismissals.json", invalidates: ["capabilities"], portability: "carry", versioned: true },
|
|
169
|
-
|
|
170
|
-
/* The secret use ledger, one row per moment the agent's exits spent a stored secret (a `{{secret:name}}`
|
|
171
|
-
* reference resolved into a shell command, a value typed into a browser field), joined onto the secrets
|
|
172
|
-
* inventory as each entry's "last used" (sandbox's secrets/secret-uses.ts). Holds names and destinations,
|
|
173
|
-
* never values, which is why it may `carry`: like the automations' run ledger, a use history is about the
|
|
174
|
-
* secrets, and an export that dropped it would arrive claiming none had ever been touched. */
|
|
175
|
-
{ path: ".intentic/records/secret-uses.json", invalidates: ["secrets"], portability: "carry" },
|
|
176
|
-
|
|
177
|
-
/* The wallet's payment ledger, one row per payment attempt that reached policy (sandbox's
|
|
178
|
-
* wallet/wallet-ledger.ts): what was paid, to whom, how it settled, with the onchain transaction hash
|
|
179
|
-
* when the endpoint stated one. Holds amounts, hosts and addresses, never a credential, the signing key
|
|
180
|
-
* never enters the container at all, so it may `carry`: like the secret-use ledger, a spend history is
|
|
181
|
-
* about the owner's money, and an export that dropped it would arrive claiming none was ever spent. */
|
|
182
|
-
{
|
|
183
|
-
path: ".intentic/records/wallet-ledger.json",
|
|
184
|
-
invalidates: [],
|
|
185
|
-
why: "Rendered through the wallet CLI and the capability card's live status probe, not from a browser query key.",
|
|
186
|
-
portability: "carry",
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
/* The named personas this sandbox shows the outside world, which connected accounts each one speaks for,
|
|
190
|
-
* what a session wearing it may do, where it works (PersonaSchema, schemas/personas.ts). It invalidates `capabilities` as well as
|
|
191
|
-
* its own key because a card and the accounts it names are read together everywhere they are shown: connect
|
|
192
|
-
* a second Reddit and the persona list has a new candidate; remove one and a card points at nothing.
|
|
193
|
-
*
|
|
194
|
-
* It is `carry`, and that is the whole design rather than an oversight, a card is a NAME and a list of ids,
|
|
195
|
-
* never a credential, so it travels to a new sandbox in full while the logins it refers to stay behind. What
|
|
196
|
-
* arrives is a workspace that already knows it has a work-reddit and a studio-x, both visibly unconnected,
|
|
197
|
-
* each waiting for one sign-in. It was also the FIRST file under .intentic the root repo tracked, and the
|
|
198
|
-
* argument it was carved out on, a card is configuration, holds no secret, and belongs in review, is the
|
|
199
|
-
* one `versioned` now generalises to the rest of the config slice (personas/personas-store.ts argues it at
|
|
200
|
-
* length, and its reasoning is why the flag exists rather than a second hand-kept list). */
|
|
201
|
-
{ path: ".intentic/config/personas.json", invalidates: ["personas", "capabilities", "manifests"], portability: "carry", versioned: true },
|
|
202
|
-
|
|
203
|
-
/* The overlay Dockerfile, four files that a single `.intentic/environment.` prefix used to cover. They are
|
|
204
|
-
* split here because they answer PORTABILITY differently while answering invalidation identically, and the
|
|
205
|
-
* split is the whole difference between an export that reproduces an environment and one that reproduces a
|
|
206
|
-
* stale copy of it:
|
|
207
|
-
* - custom is the owner-approved SOURCE OF TRUTH and the only one that must travel;
|
|
208
|
-
* - approved is COMPOSED from custom + the capability fragments + this container's base image, and is
|
|
209
|
-
* rewritten on the target's first boot, carrying it would ship a FROM naming an image the target may
|
|
210
|
-
* not be on (see composeEnvironment's baseImageOf);
|
|
211
|
-
* - the proposal and the per-tool drafts under environment.d/ are the agent's pending requests, which the
|
|
212
|
-
* owner has not answered yet; they travel so the question survives the move. */
|
|
213
|
-
{ path: ".intentic/config/environment.custom.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
214
|
-
{ path: ".intentic/config/environment.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
215
|
-
{ path: ".intentic/config/environment.d/", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
216
|
-
{
|
|
217
|
-
path: ".intentic/local/environment.approved.Dockerfile",
|
|
218
|
-
invalidates: ["environment"],
|
|
219
|
-
portability: "derived",
|
|
220
|
-
note: "The target composes its own overlay on first boot; rebuild it there to install the tools it names.",
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
{ path: ".intentic/config/settings.json", invalidates: ["settings", "manifests"], portability: "carry", versioned: true },
|
|
224
|
-
/* The safety policy the command judge reads before every flagged command (safety-policy.ts).
|
|
225
|
-
*
|
|
226
|
-
* `carry` and `versioned`, and both matter more here than for any other config file. It is a decision about
|
|
227
|
-
* how much an agent may do unasked in THIS workspace, so a fresh sandbox should arrive already governed by
|
|
228
|
-
* it rather than by the shipped default; and a change to it is exactly the kind a reviewer should see, since
|
|
229
|
-
* "since when did we stop asking about force-pushes" is a question only `git log` can answer. Being prose
|
|
230
|
-
* rather than JSON is what makes that diff worth reading.
|
|
231
|
-
*
|
|
232
|
-
* Absent is a normal state and not an unconfigured one: the daemon falls back to DEFAULT_SAFETY_POLICY,
|
|
233
|
-
* which describes the posture the product already had. */
|
|
234
|
-
{ path: ".intentic/config/safety.md", invalidates: ["safety-policy"], portability: "carry", versioned: true },
|
|
235
|
-
/* What the policy above actually decided, newest first, written several times a turn by the command gate.
|
|
236
|
-
*
|
|
237
|
-
* `derived`, and therefore under `local/` rather than beside the session transcripts in `records/`: it is
|
|
238
|
-
* evidence about what ran on THIS machine, bounded and self-trimming, and an export that carried it would
|
|
239
|
-
* arrive claiming a fresh sandbox had already judged three hundred commands. The folder is the rule here,
|
|
240
|
-
* not a filing preference — the git exclude, the search allow-list and the export bundle all read the
|
|
241
|
-
* prefix (see the layout guard in workspace-state.test.ts).
|
|
242
|
-
*
|
|
243
|
-
* Its own query key rather than the policy's, because the two change at completely different rates and a
|
|
244
|
-
* verdict landing must not invalidate the document somebody is editing. */
|
|
245
|
-
{
|
|
246
|
-
path: ".intentic/local/safety-log.json",
|
|
247
|
-
invalidates: ["safety-log"],
|
|
248
|
-
portability: "derived",
|
|
249
|
-
note: "The target starts its own record of what it decided.",
|
|
250
|
-
},
|
|
251
|
-
/* Which of the workspace's apps the daemon starts on EVERY boot (scaffold/autostart.ts). The starter-site
|
|
252
|
-
* seed writes the first entry; the `autostart` boot step reads it, which is what puts the starter's dev
|
|
253
|
-
* server up on a first boot, on a boot over a prewarmed pool volume (where the seed has nothing to do), and
|
|
254
|
-
* after every wake of a hosted machine (panels are stopped by a restart, so without this a returning user
|
|
255
|
-
* met "isn't running" every time). `carry`: an exported workspace should arrive with the same things
|
|
256
|
-
* running. Invalidates nothing: the browser reads what is running off /panels, never off this file. */
|
|
257
|
-
{
|
|
258
|
-
path: ".intentic/config/autostart.json",
|
|
259
|
-
invalidates: [],
|
|
260
|
-
why: "The browser reads what is running off /panels; this file only tells the daemon what to start at boot.",
|
|
261
|
-
portability: "carry",
|
|
262
|
-
versioned: true,
|
|
263
|
-
},
|
|
264
|
-
/* Which agent commands are heavy enough to take turns, and how many may run at once (the daemon reads it
|
|
265
|
-
* per Bash command: platform/heavy-commands.ts).
|
|
266
|
-
*
|
|
267
|
-
* `carry`, because the answer is a property of the WORKSPACE rather than of this machine: `pnpm test` fans
|
|
268
|
-
* out to the same 74 packages wherever the repo is cloned, so a fresh sandbox should arrive already knowing
|
|
269
|
-
* which commands to queue rather than rediscovering it by freezing once.
|
|
270
|
-
*
|
|
271
|
-
* `versioned` for the reason the config slice generally is (personas.json's entry argues it): the file
|
|
272
|
-
* changes at human speed, it holds no secret, and a change to it is exactly the kind a reviewer should see
|
|
273
|
-
* — raising the limit is a decision about everyone's sessions on that box, and `git log` is the only thing
|
|
274
|
-
* that answers "since when have we allowed four of these at once". */
|
|
275
|
-
{ path: ".intentic/config/heavy-commands.json", invalidates: ["settings"], portability: "carry", versioned: true },
|
|
276
|
-
/* THE SCRIPTS THE RULE TABLE RUNS, one file per reader, at the moments settings.json points them at: the
|
|
277
|
-
* per-edit linter and byte scan today (`file.edited`), whatever the owner adds beside them tomorrow.
|
|
278
|
-
*
|
|
279
|
-
* IT IS HERE BECAUSE IT WAS NOT, and the gap was silent. The root repository excludes `.intentic/config/*`
|
|
280
|
-
* with one carve-out per tracked entry, derived from this table's `versioned` flags (history.ts
|
|
281
|
-
* rootExcludes), so a directory nobody marked is ignored — and an ignored file is invisible to the land.
|
|
282
|
-
* The two scripts were written in an agent's worktree; the rules naming them were written into
|
|
283
|
-
* settings.json, which IS tracked; and only the rules arrived. What the workspace held from then on was two
|
|
284
|
-
* hooks pointing at files that did not exist: a per-edit gate that looked armed on the settings screen,
|
|
285
|
-
* spawned a process on every edit, and read nothing. The linter and the byte scan ran nowhere between an
|
|
286
|
-
* edit and a push for as long as that stood.
|
|
287
|
-
*
|
|
288
|
-
* `versioned` for the strongest form of the reason the config slice generally is. This is not a setting that
|
|
289
|
-
* decides how the sandbox behaves, it is the CODE that runs when it does, against every file an agent
|
|
290
|
-
* writes: a change here deserves review more than a change to the rule that calls it. `carry`, because it is
|
|
291
|
-
* authored text about this workspace's own conventions, holding no credential and nothing about this
|
|
292
|
-
* machine. Invalidating nothing is a real answer here rather than a gap: the settings screen renders the
|
|
293
|
-
* RULES, which live in settings.json and have their own key. */
|
|
294
|
-
{
|
|
295
|
-
path: ".intentic/config/hooks/",
|
|
296
|
-
invalidates: [],
|
|
297
|
-
why: "The settings screen renders the rules that name these scripts, out of settings.json; nothing in the browser reads the scripts themselves.",
|
|
298
|
-
portability: "carry",
|
|
299
|
-
versioned: true,
|
|
300
|
-
// The daemon never BUILDS this path, it only runs what a rule's command names, so there is no statePath
|
|
301
|
-
// call for the coverage pair to find. Whoever authors a reader is the writer here.
|
|
302
|
-
outsideWriter: "the owner or an agent, authoring them; the daemon only ever RUNS one, by the path a rule's command names",
|
|
303
|
-
},
|
|
304
|
-
// The rule table's last-fired stamps, beside the rules themselves. `derived` rather than `carry`: it is a
|
|
305
|
-
// record of what happened in THIS sandbox, and carrying it to a fresh one would date every rule to work
|
|
306
|
-
// that machine never did.
|
|
307
|
-
{
|
|
308
|
-
path: ".intentic/local/rule-firings.json",
|
|
309
|
-
invalidates: ["rule-firings"],
|
|
310
|
-
portability: "derived",
|
|
311
|
-
note: "Stamps of when each rule last did something; the new sandbox starts its own record.",
|
|
312
|
-
},
|
|
313
|
-
/* The runtime-install ledger: which tools sessions installed into the container at runtime, how often, and
|
|
314
|
-
* the last drift snapshot (environment/runtime-installs.ts). `carry` where rule-firings chose `derived`,
|
|
315
|
-
* because the two record different subjects: a firing is about what THIS machine did, while the ledger is
|
|
316
|
-
* about what this WORKSPACE's tasks keep needing — a workspace moved to a fresh sandbox will hit the same
|
|
317
|
-
* missing tools, and arriving with the recurrence memory is the whole reason it is kept. The drift snapshot
|
|
318
|
-
* inside is machine-scoped, and self-expires on the move: its bornAt can never match the new container. */
|
|
319
|
-
{ path: ".intentic/records/runtime-installs.json", invalidates: ["environment"], portability: "carry" },
|
|
320
|
-
/* Where each agent ENGINE's version comes from: the blessed list, upstream's newest, a pin, or the image
|
|
321
|
-
* (schemas/engines.ts). The versions themselves are machine state and live on the daemon's volume, because
|
|
322
|
-
* they are architecture-specific binaries; the POLICY is a decision about this workspace's work and travels
|
|
323
|
-
* with it — a team that pins Claude Code while a regression is open wants that pin to survive the move to a
|
|
324
|
-
* fresh sandbox rather than to be rediscovered by hitting the regression again.
|
|
325
|
-
*
|
|
326
|
-
* `versioned` for the config slice's usual reason (personas.json's entry argues it): it changes at human
|
|
327
|
-
* speed, holds no secret, and "since when have we been tracking upstream's newest on this repo" is a
|
|
328
|
-
* question only `git log` answers. Its own key rather than `environment`'s: the engines card is drawn on
|
|
329
|
-
* that page but reads its own route, and a channel change must not cost every open Environment tab a
|
|
330
|
-
* re-read of the overlay it did not touch. */
|
|
331
|
-
{ path: ".intentic/config/engines.json", invalidates: ["engines"], portability: "carry", versioned: true },
|
|
332
|
-
/* Written by the AGENT's file tools (the approvals skill), read by the owner's approval inbox, the one entry
|
|
333
|
-
* here whose whole point is that a change arrives from outside the browser that renders it. `authored`:
|
|
334
|
-
* an approval is text somebody wrote, a post or a description of an action, and "find the reddit post
|
|
335
|
-
* about X" is an ordinary search.
|
|
336
|
-
*
|
|
337
|
-
* `versioned` because an approval is the furthest-reaching thing the agent writes: a post goes out under the
|
|
338
|
-
* owner's name, to an audience, and cannot be recalled; an action spends or sends or deletes. The inbox
|
|
339
|
-
* already gates that, but a gate is not a record. Declining one used to erase it, so the question "what has
|
|
340
|
-
* this agent tried to do" had no answer at all, and an approved item's own history (what was proposed, what
|
|
341
|
-
* the owner changed, when it actually happened) lived only in a file nobody could diff.
|
|
342
|
-
*
|
|
343
|
-
* It costs almost nothing to track, which is why the ledger objection does not reach it: an approval is one
|
|
344
|
-
* small file, written a handful of times across its whole life (proposed → approved → done, with
|
|
345
|
-
* `finishedAt`/`result` stamped at the end), and it is KEPT afterwards rather than consumed, so tracking
|
|
346
|
-
* yields a durable record instead of the add/delete churn a queue would produce. Nothing in one is a
|
|
347
|
-
* credential: a platform, a target, the words, a description of what will be done, all of it meant to be
|
|
348
|
-
* read by the owner anyway. */
|
|
349
|
-
{ path: ".intentic/config/approvals/", invalidates: ["approvals"], portability: "carry", versioned: true, authored: true },
|
|
350
|
-
// ---- declared by the extension that renders them (contributes.files), not here ----
|
|
351
|
-
// The path is the DAEMON's (automations-store writes both), the query keys are the intentic.automations
|
|
352
|
-
// extension's. It declares them in its own manifest and the browser unions the two lists, so uninstalling
|
|
353
|
-
// the extension takes its invalidations with it instead of leaving a rule for a view that no longer exists.
|
|
354
|
-
{
|
|
355
|
-
path: ".intentic/config/automations.json",
|
|
356
|
-
invalidates: [],
|
|
357
|
-
why: "Declared by the intentic.automations extension's contributes.files, `automations` is its query key, not core's.",
|
|
358
|
-
portability: "carry",
|
|
359
|
-
versioned: true,
|
|
360
|
-
},
|
|
361
|
-
/* The run history, keyed by automation id, the LEDGER half of what automations.json used to be, and split
|
|
362
|
-
* out of it for the one reason this table's `versioned` note already gives: a tracked file must be worth
|
|
363
|
-
* reviewing. A scheduled automation records a run every time it fires, so every fire dirtied the manifest
|
|
364
|
-
* the owner reviews, and the run records went into `git log` with it, timestamps and conversation ids
|
|
365
|
-
* committed beside the prompt they belong to, burying an actual edit to the automation's config under
|
|
366
|
-
* machine noise. Config is now the only thing in the tracked file, and a fire touches nothing tracked.
|
|
367
|
-
*
|
|
368
|
-
* It is `carry` for the same reason the workflow ledger is: a run history is about the automation, not about
|
|
369
|
-
* the machine, and an export that dropped it would arrive claiming every automation had never run.
|
|
370
|
-
*
|
|
371
|
-
* Its invalidation is the extension's, exactly like the manifest above, and it has to be DECLARED there
|
|
372
|
-
* rather than inherited, because the row renders its run history from this file now: without its own entry
|
|
373
|
-
* a completed run would stop refreshing the view the moment it stopped living in automations.json. */
|
|
374
|
-
{
|
|
375
|
-
path: ".intentic/records/automation-runs.json",
|
|
376
|
-
invalidates: [],
|
|
377
|
-
why: "Declared by the intentic.automations extension's contributes.files, `automations` is its query key, not core's.",
|
|
378
|
-
portability: "carry",
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
path: ".intentic/records/approvals/",
|
|
382
|
-
invalidates: [],
|
|
383
|
-
why: "Declared by the intentic.approvals extension's contributes.files (the page that lists held wakes), `automation-approvals` is its query key, not core's.",
|
|
384
|
-
portability: "carry",
|
|
385
|
-
},
|
|
386
|
-
/* The bug-report inbox, one file per fingerprint, written by the daemon's issues-store as reports arrive
|
|
387
|
-
* from the owner's own sites and apps, and rendered by the intentic.issues extension. Its invalidation is
|
|
388
|
-
* the extension's own (`issues`), declared in that manifest, the automations shape exactly.
|
|
389
|
-
*
|
|
390
|
-
* `carry` rather than `local`: an issue is a fact about the PRODUCT, not about this container. A workspace
|
|
391
|
-
* exported and restored elsewhere that arrived claiming nothing had ever crashed would have thrown away
|
|
392
|
-
* the one record that says which bug is worth fixing first, and the counts are the whole of that record.
|
|
393
|
-
*
|
|
394
|
-
* NOT `versioned`, and the approvals entry is the contrast worth reading: an approval is authored, reviewable
|
|
395
|
-
* and acts under the owner's name, so it earns a diff. An issue is machine-recorded telemetry whose count
|
|
396
|
-
* moves on every crash: tracking it would put a commit's worth of churn in `git log` per bad afternoon,
|
|
397
|
-
* and nothing in it is a decision anybody made. */
|
|
398
|
-
{
|
|
399
|
-
path: ".intentic/records/issues/",
|
|
400
|
-
invalidates: [],
|
|
401
|
-
why: "Declared by the intentic.issues extension's contributes.files, `issues` is its query key, not core's.",
|
|
402
|
-
portability: "carry",
|
|
403
|
-
},
|
|
404
|
-
/* The maintenance ledger and probe evidence, written by the daemon's chores-store and rendered by the
|
|
405
|
-
* intentic.maintenance extension, the automations shape exactly: the path is the daemon's, the query keys
|
|
406
|
-
* (`maintenance-report`, `maintenance-runs`) are the extension's own contributes.files. Point-in-time
|
|
407
|
-
* evidence about this workspace, so `carry` like the run ledgers: an export that dropped it would arrive
|
|
408
|
-
* claiming no chore had ever been checked. */
|
|
409
|
-
{
|
|
410
|
-
path: ".intentic/records/chores/",
|
|
411
|
-
invalidates: [],
|
|
412
|
-
why: "Declared by the intentic.maintenance extension's contributes.files, `maintenance-report`/`maintenance-runs` are its query keys, not core's.",
|
|
413
|
-
portability: "carry",
|
|
414
|
-
},
|
|
415
|
-
/* The documentation STAGING tree (documentation extension's paths.ts): generation writes here, the owner
|
|
416
|
-
* reads and approves here, publishing copies into the repo. `authored` is the whole nature of the entry,
|
|
417
|
-
* these are draft READMEs, approvals-shaped in every way that matters, and "find the staged page about X" is
|
|
418
|
-
* as ordinary a search as finding a post draft. */
|
|
419
|
-
{
|
|
420
|
-
path: ".intentic/config/docs/",
|
|
421
|
-
invalidates: [],
|
|
422
|
-
why: "Declared by the intentic.documentation extension's contributes.files, `documentation`/`documentation-runs` are its query keys, not core's.",
|
|
423
|
-
portability: "carry",
|
|
424
|
-
authored: true,
|
|
425
|
-
outsideWriter: "the intentic.documentation extension's staging writes (its paths.ts)",
|
|
426
|
-
},
|
|
427
|
-
/* The workflow designs and their run ledger became CORE keys the day runs got cards on the fleet board and
|
|
428
|
-
* a mode of the chat panel (web's useWorkflowRuns): those surfaces exist whether or not the workflows
|
|
429
|
-
* extension is enabled, so their freshness cannot ride an extension's contributes.files, an owner turning
|
|
430
|
-
* the extension off would have frozen the board's run cards mid-run. This push is the ONLY live feed the
|
|
431
|
-
* run surfaces have: the scheduler writes the ledger several times per step and nothing polls for it.
|
|
432
|
-
* The runs file invalidates `workflows` too, because GET /workflows embeds each design's runs
|
|
433
|
-
* (WorkflowSummary), a settled step changes that answer as surely as an edited design does. */
|
|
434
|
-
{ path: ".intentic/config/workflows.json", invalidates: ["workflows"], portability: "carry", versioned: true },
|
|
435
|
-
{ path: ".intentic/records/workflow-runs.json", invalidates: ["workflows", "workflow-runs"], portability: "carry" },
|
|
436
|
-
/* The SAVED loops, which are a manifest and so the opposite of the ledger below them: a handful of entries
|
|
437
|
-
* a person authors, read by two surfaces at once, the workflows page that owns them, and every chat
|
|
438
|
-
* composer's loop picker. Those two are in different windows as often as not (a popped-out chat is its own
|
|
439
|
-
* window), so an edit made on the page has to reach a picker nobody is going to think to reopen. A CORE key
|
|
440
|
-
* rather than the workflows extension's, for the reason the workflow designs beside it are: the composer
|
|
441
|
-
* lists saved loops whether or not that extension is switched on. */
|
|
442
|
-
{ path: ".intentic/config/loop-designs.json", invalidates: ["loop-designs"], portability: "carry", versioned: true },
|
|
443
|
-
{
|
|
444
|
-
path: ".intentic/records/loops.json",
|
|
445
|
-
invalidates: [],
|
|
446
|
-
why: "Ralph loops and their iteration history. Nothing observes it: where a RUNNING loop stands rides on the fleet roster (AgentSummary.loop), which the /events stream already pushes about once a second, and a second source invalidating on this file could only ever disagree with the card beside it. The iteration list of an ENDED loop is an on-demand read, nothing renders it until someone opens it (web's useLoops, which holds no query for exactly this reason).",
|
|
447
|
-
portability: "carry",
|
|
448
|
-
},
|
|
449
|
-
|
|
450
|
-
/* ---- reached by no query, for reasons that are not oversights ----
|
|
451
|
-
*
|
|
452
|
-
* This channel's currency is a QUERY KEY, and invalidation only reaches a query something is observing.
|
|
453
|
-
* Both entries below are outside that by design, so an empty set is the honest record, naming a key no
|
|
454
|
-
* query uses would put the drift this table exists to remove straight back into it. Each says which
|
|
455
|
-
* constraint would have to move first, so the next reader doesn't re-derive it. */
|
|
456
|
-
{
|
|
457
|
-
path: ".intentic/records/webchat-installs.json",
|
|
458
|
-
invalidates: [],
|
|
459
|
-
why: "Which origins have loaded a Front Desk's widget, written on a 30s flush timer while a customer's site serves page views. The install panel that renders it fetches on open and polls itself while it is on screen, which is the whole window in which the answer changes for anyone. Pushing instead would bill every connected browser a refetch per flush, for a panel almost nobody has open.",
|
|
460
|
-
portability: "carry",
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
path: ".intentic/records/issue-installs.json",
|
|
464
|
-
invalidates: [],
|
|
465
|
-
why: "The same probe for the bug reporter's script, on the same flush timer and read by the same kind of panel, so it is outside the push path for the same reason the Front Desk's is.",
|
|
466
|
-
portability: "carry",
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
path: ".intentic/records/thread-sessions.json",
|
|
470
|
-
invalidates: [],
|
|
471
|
-
why: "Thread bookkeeping (an inbound thread, a Front Desk visitor, a Discord or Slack channel, → sandbox conversation + provider session), written on EVERY inbound message. Nothing in the browser reads it: what a thread produces is a conversation, and the fleet board already learns about that from the agent registry's own push. Naming a key here would bill every connected browser a refetch per inbound message, the request storm this table's own note warns about, to refresh nothing it can see.",
|
|
472
|
-
portability: "carry",
|
|
473
|
-
},
|
|
474
|
-
/* SPLIT, so that "what an extension is configured to do" and "the token it does it with" stop being one file.
|
|
475
|
-
*
|
|
476
|
-
* This entry used to be `secret` and untracked, classed by what a value COULD hold: values are a primitive
|
|
477
|
-
* union an extension chooses the meaning of, and "an API key for the service I talk to" is squarely within
|
|
478
|
-
* it. That classification was honest about the risk and wrong about the file, it meant an extension's whole
|
|
479
|
-
* configuration was unreviewable because one of its keys might be a credential, AND the credential was in
|
|
480
|
-
* there anyway, in a file the workspace API does not lock. A turn could simply read it.
|
|
481
|
-
*
|
|
482
|
-
* A descriptor already says which keys those are (`contributes.settings[].secret`), so the values it names
|
|
483
|
-
* now live in the vault off /work and this file keeps the rest, the capability manifest's split, applied to
|
|
484
|
-
* the same problem one table over (extensions/extension-settings.ts holds it, and the reasoning). Reads
|
|
485
|
-
* rehydrate, so no caller changed.
|
|
486
|
-
*
|
|
487
|
-
* What the split earns: `carry`, because what is left is an extension's configuration and a bundle should
|
|
488
|
-
* arrive with it; and `versioned`, because turning an extension's behaviour on is a decision, and the file
|
|
489
|
-
* that records it can now be read without reading anybody's token. The boot sweep is what keeps that true of
|
|
490
|
-
* a file the agent can also edit, see vaultExtensionSettingSecrets.
|
|
491
|
-
*
|
|
492
|
-
* NO `note`, and the split is why: a note is printed by the import report beside a SKIPPED entry, so an entry
|
|
493
|
-
* that carries can never show one. "Re-enter the credentials" is now the vault's instruction to give, and the
|
|
494
|
-
* vault is under `.intentic/auth/`, which is skipped, and says so there. */
|
|
495
|
-
{
|
|
496
|
-
path: ".intentic/config/extension-settings.json",
|
|
497
|
-
invalidates: [],
|
|
498
|
-
why: "Held in a module-level shallowRef store per extension (web's extensionSettingsStore) with no query observer, and deliberately so: api.settings.get must answer SYNCHRONOUSLY from an extension's first activate() line, and the store outlives every component scope. A module-level QueryObserver is the one shape that would make invalidation refetch, and this app already ruled it out, it detaches on the queryClient.clear() at logout (see useSandbox's sandbox-list mirror). So a remote member's setting edit reaches this browser on its next load, not live.",
|
|
499
|
-
portability: "carry",
|
|
500
|
-
versioned: true,
|
|
501
|
-
},
|
|
502
|
-
/* Unlike the settings file above it, the on/off switch IS observed by a query, the Extensions tab's list,
|
|
503
|
-
* which carries each row's switch position, so a flip made elsewhere (another member, the agent writing the
|
|
504
|
-
* file) shows up here live. It does not re-run the host: activating or retiring an extension is the loader's
|
|
505
|
-
* reconcile, which the tab's own toggle triggers, so a remote flip takes effect on this browser's next load. */
|
|
506
|
-
{
|
|
507
|
-
path: ".intentic/config/extension-enablement.json",
|
|
508
|
-
invalidates: ["extensions"],
|
|
509
|
-
portability: "carry",
|
|
510
|
-
versioned: true,
|
|
511
|
-
},
|
|
512
|
-
/* Workspace extensions: one directory per extension, consumed straight from the workspace, no clone, no
|
|
513
|
-
* install moment. Written like approvals, by the agent's own file tools (which is the point: an agent authors
|
|
514
|
-
* an extension and it is live for the daemon and every session at once, since .intentic is shared), so this
|
|
515
|
-
* push is what makes one appearing or changing show up on the Extensions tab while the owner watches.
|
|
516
|
-
* `authored` for the same reason as approvals: this is source the agent wrote and will be asked to find,
|
|
517
|
-
* unlike `.intentic/extensions/` below, which is CLONES of source that lives elsewhere.
|
|
518
|
-
*
|
|
519
|
-
* `versioned` FOR THAT SAME REASON, which is the whole argument. Every other load path an extension can take
|
|
520
|
-
* is already reviewable by construction: a git-installed one is a sha in `capabilities.json` that an owner
|
|
521
|
-
* approved, a baked one shipped in the image. This one is neither, it is code that appears because an agent
|
|
522
|
-
* wrote a file, runs in the app on the owner's session, may register a rail tile, and may serve HTTP from a
|
|
523
|
-
* node process with the workspace under `node:fs` and whatever `permissions.daemon` names. Untracked, the
|
|
524
|
-
* switch that turns it on was in `git log` (extension-enablement.json, below) while the thing being switched
|
|
525
|
-
* on was not: a commit could record enabling something nobody else could read. It is also the one extension
|
|
526
|
-
* kind with no install moment to review at, so the diff is the only review there is.
|
|
527
|
-
*
|
|
528
|
-
* Not a ledger and not bulk: a handful of small authored files per extension, written when someone edits them.
|
|
529
|
-
* The daemon restarts the backend host on a change here, so an edit is already a consequential event, this
|
|
530
|
-
* makes it a legible one. */
|
|
531
|
-
{ path: ".intentic/config/workspace-extensions/", invalidates: ["extensions"], portability: "carry", versioned: true, authored: true },
|
|
532
|
-
/* What the registry comparison found per installed extension (update available / advisory / post-update
|
|
533
|
-
* health), written by the periodic check and by the update/revert transactions, pushed to the tab because
|
|
534
|
-
* an advisory that auto-disabled something must not wait for a reload to be seen. */
|
|
535
|
-
{ path: ".intentic/records/extension-updates.json", invalidates: ["extensions"], portability: "carry" },
|
|
536
|
-
/* The owner's per-extension update posture (notify / agent / auto, and the advisory opt-out). Carried:
|
|
537
|
-
* it is a decision about the extension, not about this machine. */
|
|
538
|
-
{ path: ".intentic/config/extension-update-policy.json", invalidates: ["extensions"], portability: "carry", versioned: true },
|
|
539
|
-
/* Carried, because the evidence is about the extension rather than about the machine: an export that dropped
|
|
540
|
-
* it would arrive claiming every permission was unused, which is worse than arriving with no figures at all. */
|
|
541
|
-
{
|
|
542
|
-
path: ".intentic/records/extension-usage.json",
|
|
543
|
-
invalidates: [],
|
|
544
|
-
why: "Which of the routes each extension DECLARED it has actually called, the evidence behind the permissions list on its row. The one entry here whose empty set is a RATE decision rather than an architectural one: every browser with the app open reports its batch on a timer, so wiring this to the `extensions` query would refetch the whole list every few seconds for a figure nobody is watching change. The tab reads it when it loads, which is when anyone is reading it.",
|
|
545
|
-
portability: "carry",
|
|
546
|
-
},
|
|
547
|
-
/* THE ONE ENTRY WHERE "HOLDS NO CREDENTIAL" IS TRUE AND `versioned` IS STILL WRONG, which is worth stating
|
|
548
|
-
* because it looks like the two above it: an email and a role per row, nothing to vault, and "who may drive
|
|
549
|
-
* this sandbox" is as consequential a fact as any this table tracks.
|
|
550
|
-
*
|
|
551
|
-
* It stays out for two reasons that are not about secrecy. It is a MIRROR, the platform's invite records are
|
|
552
|
-
* the grant, this is the copy the enforcer keeps so a grant it never received is never honoured, and a change
|
|
553
|
-
* here is the two disagreeing rather than anyone deciding something. Review of the decision already exists,
|
|
554
|
-
* on the Access tab, against the record that is authoritative. And tracking it would mean reclassifying it
|
|
555
|
-
* `carry` to satisfy the guard, which is the one thing it must never be: an access list that travelled would
|
|
556
|
-
* let a source sandbox hand itself the target's ownership. Widening the guard for this single entry is the
|
|
557
|
-
* worse trade, it protects every `identity` entry, and most of those ARE credentials. */
|
|
558
|
-
{
|
|
559
|
-
path: ".intentic/identity/members.json",
|
|
560
|
-
invalidates: [],
|
|
561
|
-
why: "Not this view's source at all: SandboxAccess renders the PLATFORM's invite records (apiClient.invite.list), and this file is the daemon's ENFORCED copy, written first so a grant the enforcer never got is never recorded, then never read back. A change here means the two disagreed, which the write order makes fail-closed rather than stale.",
|
|
562
|
-
portability: "identity",
|
|
563
|
-
note: "Re-invite collaborators from the Access tab, a grant is the platform's record, and the target enforces its own copy.",
|
|
564
|
-
},
|
|
565
|
-
|
|
566
|
-
// ---- daemon-owned, nothing derives from watching them ----
|
|
567
|
-
/* Keep credentials and conversation state in disjoint top-level trees. Provider homes are intentionally
|
|
568
|
-
* classified as a single secret unit: several CLIs mix OAuth, config, and provider-native thread metadata,
|
|
569
|
-
* and no generic export can safely distinguish those files. The broad root also makes a newly-added provider
|
|
570
|
-
* secret by construction instead of relying on another hand-maintained provider-name list.
|
|
571
|
-
*
|
|
572
|
-
* IT IS NO LONGER ONLY THE AI LOGINS. Both credential splits put their vault here, `capability-secrets.json`
|
|
573
|
-
* and `extension-secrets.json`, sited beside the provider homes precisely because this tree is already
|
|
574
|
-
* outside the file routes, the workspace walk and the search index (composition.ts sites them, and the two
|
|
575
|
-
* stores argue why). So this is now the ONE entry a secret-less bundle leaves behind, and its note is
|
|
576
|
-
* therefore the only place the owner is told what to re-enter: the manifests that name those connections
|
|
577
|
-
* travel, and would otherwise arrive looking complete. */
|
|
578
|
-
{
|
|
579
|
-
path: ".intentic/secrets/auth/",
|
|
580
|
-
invalidates: [],
|
|
581
|
-
why: "AI-provider credentials and runtime homes, plus the capability and extension-settings secret vaults; each account is rendered through owner-gated provider routes.",
|
|
582
|
-
portability: "secret",
|
|
583
|
-
note: "Sign the agent's AI accounts in again on the Agent tab, then re-enter each connection's credential on Capabilities and each extension's secret settings on Extensions, both arrived listed but unauthenticated.",
|
|
584
|
-
},
|
|
585
|
-
/* Agent session transcripts, rewritten on every streamed token: nothing renders them off disk, so nothing
|
|
586
|
-
* under here is watched. The exclusion is a DESCENT filter, which is what makes it cheap: the watcher never
|
|
587
|
-
* walks `projects` and its per-slug subtrees at all. Measured on the live workspace, descending would add
|
|
588
|
-
* +119 watched directories against ~593 (a fifth more), with 314 continuously-rewritten transcripts inside
|
|
589
|
-
* the newly-watched set. If a surface here ever needs to be live, weigh that 20% against a poll first. */
|
|
590
|
-
{
|
|
591
|
-
path: ".intentic/records/sessions/claude/",
|
|
592
|
-
invalidates: [],
|
|
593
|
-
why: "Agent session transcripts; nothing derives from watching them, and descending into them would cost a fifth of the watcher.",
|
|
594
|
-
portability: "carry",
|
|
595
|
-
},
|
|
596
|
-
{
|
|
597
|
-
path: ".intentic/records/artifacts/",
|
|
598
|
-
invalidates: [],
|
|
599
|
-
why: "Durable outputs owned by conversations and extension runs: attachments, browser captures, generated images, acceptance reports, workflow step reports, voice transcripts, and loop ledgers.",
|
|
600
|
-
portability: "carry",
|
|
601
|
-
},
|
|
602
|
-
{
|
|
603
|
-
path: ".intentic/local/cache/",
|
|
604
|
-
invalidates: [],
|
|
605
|
-
why: "Rebuildable indexes and caches, the iq index and its vector sidecar, the whisper model, fileq's derived/ markdown shadows of binary files; ignored by the watcher and recreated from carried workspace content.",
|
|
606
|
-
portability: "derived",
|
|
607
|
-
},
|
|
608
|
-
/* Connector and extension scratch, one directory per extension under runtime/extensions/<id>
|
|
609
|
-
* (extensionRuntimeDir below, the ONLY way an extension names a home here, so a new one lands under its
|
|
610
|
-
* own id by construction instead of minting a file at the .intentic root). Resume watermarks, cached
|
|
611
|
-
* hour-tokens, gateway discovery state: all of it either expires or re-establishes itself, and classifying
|
|
612
|
-
* the root once is what keeps a token an extension caches tomorrow out of bundles without a second edit. */
|
|
613
|
-
{
|
|
614
|
-
path: ".intentic/local/runtime/",
|
|
615
|
-
invalidates: [],
|
|
616
|
-
why: "Extension runtime scratch (watermarks, cached short-lived tokens); nothing renders it and gateways re-derive it.",
|
|
617
|
-
portability: "derived",
|
|
618
|
-
outsideWriter: "extensions, through extensionRuntimeDir below",
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
path: ".intentic/local/tmp/",
|
|
622
|
-
invalidates: [],
|
|
623
|
-
why: "Scratch that agents and tools leave behind (build logs, demo checkouts); nothing reads it after the turn that wrote it. The state janitor empties it at boot.",
|
|
624
|
-
portability: "derived",
|
|
625
|
-
},
|
|
626
|
-
/* Not written by the daemon at all: pnpm auto-creates its content-addressable store at the project's
|
|
627
|
-
* mountpoint, and `.intentic` is its own mount in an isolated turn, so an install run from under it mints
|
|
628
|
-
* this. Declared anyway, because the table's job is to say what everything under `.intentic` IS: hardlink
|
|
629
|
-
* sources a fresh install rebuilds, which an export must not ship (it reached 1.3 GB on the workspace this
|
|
630
|
-
* entry was written against). */
|
|
631
|
-
{
|
|
632
|
-
path: ".intentic/local/.pnpm-store/",
|
|
633
|
-
invalidates: [],
|
|
634
|
-
why: "pnpm's content-addressable store, auto-created by installs run from under .intentic; the next install rebuilds it.",
|
|
635
|
-
portability: "derived",
|
|
636
|
-
outsideWriter: "pnpm itself, when an install runs from under .intentic",
|
|
637
|
-
},
|
|
638
|
-
{
|
|
639
|
-
path: ".intentic/local/newest-run.json",
|
|
640
|
-
invalidates: [],
|
|
641
|
-
why: "The newest daemon version that ever ran this workspace (store/newest-run.ts), a downgrade tripwire, about THIS sandbox the way rule-firings is.",
|
|
642
|
-
portability: "derived",
|
|
643
|
-
note: "The target stamps its own daemon version on first boot.",
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
path: ".intentic/records/verify.json",
|
|
647
|
-
invalidates: [],
|
|
648
|
-
why: "The dependency verifier's verdict memory; nothing renders it directly, outcomes reach the owner as activity entries and workspace events.",
|
|
649
|
-
portability: "carry",
|
|
650
|
-
},
|
|
651
|
-
{
|
|
652
|
-
path: ".intentic/local/verify/",
|
|
653
|
-
invalidates: [],
|
|
654
|
-
why: "A running check's wrapper artifacts (log + exit status), read once by the daemon when the panel finishes.",
|
|
655
|
-
portability: "derived",
|
|
656
|
-
},
|
|
657
|
-
{
|
|
658
|
-
path: ".intentic/secrets/ci.json",
|
|
659
|
-
invalidates: [],
|
|
660
|
-
why: "Webhook secret + conclusion memory; the Pipelines view reads it through /ci/runs, not off disk.",
|
|
661
|
-
portability: "secret",
|
|
662
|
-
note: "Re-add the CI webhook on the Pipelines view, its secret is per-sandbox.",
|
|
663
|
-
},
|
|
664
|
-
/* THE ONE ENTRY THAT OPTS OUT OF THE BACKUP, and the reason the flag exists rather than the rule simply
|
|
665
|
-
* reading `portability !== "derived"`. It is `identity` like the three below it, so the derived answer would
|
|
666
|
-
* copy it down with them, but where those are a name, a workspace id and a role per row, these are tokens
|
|
667
|
-
* that AUTHENTICATE against this sandbox from outside it. Hashed, which lowers the stakes and does not
|
|
668
|
-
* settle them: the point of a backup is to be readable after the thing it backs up is gone, and a file whose
|
|
669
|
-
* only purpose is to admit callers has no business sitting in one. Nothing is lost by leaving it out, the
|
|
670
|
-
* entry's own note already says the tokens must be re-minted on any new sandbox, so a copy could never have
|
|
671
|
-
* been restored anyway. */
|
|
672
|
-
{
|
|
673
|
-
path: ".intentic/identity/control-tokens.json",
|
|
674
|
-
invalidates: [],
|
|
675
|
-
why: "Hashed control tokens (the ACP editor bridge, and anything else driving this sandbox from outside), listed on demand by the owner.",
|
|
676
|
-
portability: "identity",
|
|
677
|
-
backup: false,
|
|
678
|
-
note: "Mint fresh control tokens, the old ones authenticate against the source sandbox.",
|
|
679
|
-
},
|
|
680
|
-
{
|
|
681
|
-
path: ".intentic/identity/owner.json",
|
|
682
|
-
invalidates: [],
|
|
683
|
-
why: "Bound once on first use; a change here means the sandbox was re-owned, which re-authenticates anyway.",
|
|
684
|
-
portability: "identity",
|
|
685
|
-
},
|
|
686
|
-
{
|
|
687
|
-
path: ".intentic/identity/workspace.json",
|
|
688
|
-
invalidates: [],
|
|
689
|
-
why: "The workspace identity, read from the /events hello frame rather than as a file.",
|
|
690
|
-
portability: "identity",
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
path: ".intentic/config/templates.json",
|
|
694
|
-
invalidates: [],
|
|
695
|
-
why: "Scaffold templates, read when the scaffold dialog opens.",
|
|
696
|
-
portability: "carry",
|
|
697
|
-
versioned: true,
|
|
698
|
-
},
|
|
699
|
-
/* Classed `derived` for size rather than for safety, and it is the one entry where that costs the owner
|
|
700
|
-
* something real: the profiles ARE logged-in sessions. They are also gigabytes of a store Chromium rewrites
|
|
701
|
-
* constantly and versions against its own build, so carrying them ships bulk that the target's Chromium may
|
|
702
|
-
* refuse anyway. The note is what keeps the loss visible instead of silent. */
|
|
703
|
-
{
|
|
704
|
-
path: ".intentic/local/browser/",
|
|
705
|
-
invalidates: [],
|
|
706
|
-
why: "Browser-login profiles: Chromium rewrites these constantly. Descent-ignored by the watcher outright.",
|
|
707
|
-
portability: "derived",
|
|
708
|
-
note: "Log the agent's browser back into any site it needs, profiles do not travel.",
|
|
709
|
-
},
|
|
710
|
-
{
|
|
711
|
-
path: ".intentic/local/extensions/",
|
|
712
|
-
invalidates: [],
|
|
713
|
-
why: "Extension checkouts, whole git clones. The `extensions` query is driven by the capability manifest above, not by their contents.",
|
|
714
|
-
portability: "derived",
|
|
715
|
-
note: "Extensions re-clone from the capability manifest on the target's next reconcile.",
|
|
716
|
-
},
|
|
717
|
-
{ path: ".intentic/records/plugins/", invalidates: [], why: "Agent plugin dirs, read by the SDK's loader each turn.", portability: "carry" },
|
|
718
|
-
/* THE SKILLS THE OWNER WROTE THEMSELVES, one directory per skill, the source of truth the reconciler copies
|
|
719
|
-
* into `.agents/skills` for the ones currently switched on (settings.json's `skills` list). It is here rather
|
|
720
|
-
* than in the loaded folder for the reason the plugin dirs are: that tree holds only what is currently ON,
|
|
721
|
-
* and a skill switched off has to keep its text somewhere the loaders will not read it from.
|
|
722
|
-
*
|
|
723
|
-
* `versioned`, like the rest of the config slice: a skill changes how the agent behaves, so it earns a diff
|
|
724
|
-
* in the Changes review and a line in `git log` the same way a rule or a persona does. `carry` for the same
|
|
725
|
-
* reason, it is text the owner wrote, with no credential in it and nothing about this machine. */
|
|
726
|
-
{ path: ".intentic/config/skills/", invalidates: ["skills"], portability: "carry", versioned: true },
|
|
727
|
-
/* ONE FOLDER PER PERSONA, what a session wearing that card is told, and the skills and tools only it gets.
|
|
728
|
-
* Laid out as a Claude Code plugin (`.claude-plugin/plugin.json`, `skills/`, `agents/`, `commands/`,
|
|
729
|
-
* `hooks/`, `.mcp.json`) so the runtime's own loader reads it and this daemon parses none of it, exactly as
|
|
730
|
-
* the plugin checkouts above are read (personas/persona-kit.ts).
|
|
731
|
-
*
|
|
732
|
-
* A SECOND ENTRY BESIDE `personas.json` RATHER THAN A FIELD INSIDE IT, because the two are different kinds
|
|
733
|
-
* of thing to review. The card is a name, some ids and some switches, a few lines that diff cleanly. This
|
|
734
|
-
* is prose and files: a system prompt, a skill, a subagent. Folding a 20k prompt into the JSON would make
|
|
735
|
-
* every persona edit an unreadable diff and put text somebody wrote inside a record nobody writes by hand.
|
|
736
|
-
*
|
|
737
|
-
* `versioned` and `carry` for the same reasons the card and the skills above are: it changes how the agent
|
|
738
|
-
* behaves, it holds no credential, and it belongs in a pull request, which is also what makes it
|
|
739
|
-
* searchable, since every versioned entry already is. */
|
|
740
|
-
{ path: ".intentic/config/personas/", invalidates: ["personas"], portability: "carry", versioned: true },
|
|
741
|
-
|
|
742
|
-
/* THE CONTEXT SHELVES, one JSON file per shelf (schemas/context.ts): which part of the workspace a
|
|
743
|
-
* conversation opened on it carries. `versioned` and `carry` on the persona card's own argument, a shelf is
|
|
744
|
-
* a list of item ids and holds no credential, and which repositories a session can see is exactly the kind
|
|
745
|
-
* of decision that belongs in a pull request. */
|
|
746
|
-
{ path: ".intentic/config/context/", invalidates: ["context"], portability: "carry", versioned: true },
|
|
747
|
-
] as const satisfies readonly WorkspaceStateFile[];
|
|
748
|
-
|
|
749
|
-
export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = STATE_FILES;
|
|
750
|
-
|
|
751
|
-
/* The entries the root repo tracks, workspace-root-relative and in declaration order, what history.ts turns
|
|
752
|
-
* into the negations that carve them back out of the wholesale `.intentic` exclusion.
|
|
753
|
-
*
|
|
754
|
-
* Derived rather than written down beside the exclude rule, for the reason this whole file exists: the git rule
|
|
755
|
-
* lives in the daemon and the classification lives here, and a second hand-kept copy of "which config is
|
|
756
|
-
* reviewable" is a copy that goes stale the first time someone adds a store. Marking an entry `versioned` is now
|
|
757
|
-
* the entire change, the exclude list follows on the next boot, in both places it is written. */
|
|
758
|
-
export const VERSIONED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned).map((file) => file.path);
|
|
759
|
-
|
|
760
|
-
/* The `.intentic` slice a workspace SEARCH may surface: configuration a person reviews (`versioned`) plus the
|
|
761
|
-
* authored-content dirs (`authored`), approvals, staged docs, workspace extensions. Everything else under
|
|
762
|
-
* `.intentic` is machine state, and the search engine (iq's floor) denies it BY DEFAULT off this list, the
|
|
763
|
-
* same default-deny the portability classes are built on and for the same reason: a deny list is a list a new
|
|
764
|
-
* ledger is forgotten from, and the forgetting is silent, it ranked loop iteration history and cloned
|
|
765
|
-
* third-party extension source against the user's own code for months before this derivation existed.
|
|
766
|
-
*
|
|
767
|
-
* WHAT THE CREDENTIAL SPLITS MOVED ACROSS THIS LINE, since the note that used to sit here said the opposite and
|
|
768
|
-
* was worth replacing rather than deleting. `capabilities.json` was `secret` and unversioned, and the sentence
|
|
769
|
-
* celebrated that the index therefore stopped copying capability tokens into search text. It is `versioned` now
|
|
770
|
-
* and searchable, and the guarantee is unchanged, because the tokens are not in the file any more. The floor
|
|
771
|
-
* moved from "keep the index away from the file that holds credentials" to "the file holds none", which is the
|
|
772
|
-
* stronger of the two: it also holds for the shell, which never consulted this list at all. `auth/`, where those
|
|
773
|
-
* values went, both vaults included, is still denied, and is the entry that was doing the real work all along. */
|
|
774
|
-
export const SEARCHABLE_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned || file.authored).map(
|
|
775
|
-
(file) => file.path,
|
|
776
|
-
);
|
|
777
|
-
|
|
778
|
-
/* WHAT KIND OF THING THIS IS, in the one word a person browsing the state dir would use, and the axis the
|
|
779
|
-
* DIRECTORY LAYOUT is built on, so the folder you open explains itself before you read a table about it.
|
|
780
|
-
*
|
|
781
|
-
* It is DERIVED, and that is the whole reason it can be trusted. Forty-nine entries already answer three
|
|
782
|
-
* questions between them (is it reviewed, is it authored, does it travel), and those answers turn out to nest
|
|
783
|
-
* perfectly rather than cut across each other: every `versioned` entry is `carry`, every `authored` entry is
|
|
784
|
-
* `carry`, and nothing is both a credential and a thing a person edits. A nested set of answers is exactly what
|
|
785
|
-
* a directory tree can express, which is why five folders can carry rules that used to take five hand-kept path
|
|
786
|
-
* lists, the git exclude, the search allow-list, the sync ignore, the watcher skip, the export bundle.
|
|
787
|
-
*
|
|
788
|
-
* Declaring the group on each entry instead would have made it a fourth independent fact to keep in step with
|
|
789
|
-
* the other three, which is the failure this file exists to argue against. Adding a store still means answering
|
|
790
|
-
* the same three questions it always did; the group, the folder it belongs in, and every rule that reads them
|
|
791
|
-
* follow with no further edit. */
|
|
792
|
-
export type StateGroup =
|
|
793
|
-
/* Reviewed and reviewable: settings, personas, skills, approvals, staged docs, the environment overlay. Tracked
|
|
794
|
-
* by the root repo, searchable, backed up, and carried into a new sandbox. Two of its members (approvals, staged
|
|
795
|
-
* docs) are authored content rather than configuration, and the folder is still called `config`, the word
|
|
796
|
-
* that makes seventeen of the nineteen instantly clear beats one that makes all nineteen vague. */
|
|
797
|
-
| "config"
|
|
798
|
-
/* What HAPPENED here, run ledgers, approvals, chores, transcripts, artifacts. Machine-written, so untracked
|
|
799
|
-
* and unsearchable, but the owner's history all the same: backed up and carried. */
|
|
800
|
-
| "records"
|
|
801
|
-
/* Rebuildable from something that does travel: caches, indexes, extension checkouts, scratch, the composed
|
|
802
|
-
* overlay, browser profiles. Neither backed up nor carried, and the janitor may delete it. `local` in the
|
|
803
|
-
* sense every other tool uses it, belongs to this machine, is not shared, and losing it costs nothing. */
|
|
804
|
-
| "local"
|
|
805
|
-
/* Who owns this sandbox and who may drive it. Backed up so the owner keeps a copy of their own access, never
|
|
806
|
-
* carried, a list that travelled would let a source sandbox claim the target. */
|
|
807
|
-
| "identity"
|
|
808
|
-
/* Credentials. Never backed up; carried only when the owner opts in at export and the bundle records it. */
|
|
809
|
-
| "secrets";
|
|
810
|
-
|
|
811
|
-
/* THE FOLDER EACH GROUP LIVES IN.
|
|
812
|
-
*
|
|
813
|
-
* The group name IS the directory name, one vocabulary, not a name and a translation of it. That is what lets
|
|
814
|
-
* the guard in workspace-state.test.ts check the whole layout with one rule ("every entry sits under its own
|
|
815
|
-
* group's folder") rather than trusting forty-nine literals to have been typed correctly, and it is why renaming
|
|
816
|
-
* a folder is an edit here plus the literals the compiler then points at, with nothing able to half-move.
|
|
817
|
-
*
|
|
818
|
-
* WHICH RULES THE LAYOUT ACTUALLY CARRIES, stated plainly because it is fewer than the tidy version of this
|
|
819
|
-
* story. The sync backup collapses to two folder names (BACKUP_IGNORES) and workspace search to one, because
|
|
820
|
-
* "may the owner keep this" and "is this authored text" are exactly what the grouping sorts on. Two others do
|
|
821
|
-
* NOT collapse, and both are worth knowing about before someone tries:
|
|
822
|
-
* - THE GIT EXCLUDE tracks `versioned`, which is eighteen of `config`'s nineteen. The exception is the staged
|
|
823
|
-
* docs tree: searchable, deliberately untracked (publishing copies those pages into the repo, so tracking
|
|
824
|
-
* the staging copy too would double every one of them). A `config/` prefix would quietly start tracking it.
|
|
825
|
-
* - THE WATCHER skips what churns, which is most of `local` but not all of it: the composed overlay and the
|
|
826
|
-
* rule-firing stamps are `derived` and therefore `local`, and both still feed a view. A `local/` prefix
|
|
827
|
-
* would stop the environment page refreshing when the overlay is recomposed.
|
|
828
|
-
* Both stay derived from the flags instead, which costs a longer generated list and no correctness. The folders
|
|
829
|
-
* are the layout; the flags are still the authority. */
|
|
830
|
-
export const STATE_GROUP_DIR: Readonly<Record<StateGroup, string>> = {
|
|
831
|
-
config: `${STATE_DIR}/config`,
|
|
832
|
-
records: `${STATE_DIR}/records`,
|
|
833
|
-
local: `${STATE_DIR}/local`,
|
|
834
|
-
identity: `${STATE_DIR}/identity`,
|
|
835
|
-
secrets: `${STATE_DIR}/secrets`,
|
|
836
|
-
};
|
|
837
|
-
|
|
838
|
-
// Every group, derived off the folder map so the two can never disagree about how many there are. Declaration
|
|
839
|
-
// order is the order a person should read them in: what you wrote, what happened, what can be thrown away, who
|
|
840
|
-
// owns this, and the keys.
|
|
841
|
-
export const STATE_GROUPS = Object.keys(STATE_GROUP_DIR) as readonly StateGroup[];
|
|
842
|
-
|
|
843
|
-
/* The group each entry falls in. Ordered most-specific-first: a credential is a credential whatever else it is,
|
|
844
|
-
* and only once those are out of the way does "did a person write this" separate the two `carry` groups. */
|
|
845
|
-
export const stateGroupOf = (file: WorkspaceStateFile): StateGroup => {
|
|
846
|
-
switch (file.portability) {
|
|
847
|
-
case "secret":
|
|
848
|
-
return "secrets";
|
|
849
|
-
case "identity":
|
|
850
|
-
return "identity";
|
|
851
|
-
case "derived":
|
|
852
|
-
return "local";
|
|
853
|
-
case "carry":
|
|
854
|
-
return file.versioned === true || file.authored === true ? "config" : "records";
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
|
|
858
|
-
// The entries of one group, workspace-root-relative and in declaration order, what each rule that used to keep
|
|
859
|
-
// its own path list now asks for instead.
|
|
860
|
-
export const stateGroupPaths = (group: StateGroup): readonly string[] =>
|
|
861
|
-
WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group).map((file) => file.path);
|
|
862
|
-
|
|
863
|
-
/* WHAT AN ISOLATED TURN SHARES LIVE WITH THE MAIN TREE, and what is its own. The state dir is split along ONE
|
|
864
|
-
* line, and it is the line git already draws: what the root repo TRACKS (`versioned`) is the worktree's own
|
|
865
|
-
* checkout, edited on the agent's branch, reviewed in its diff and landed like code; everything git does NOT
|
|
866
|
-
* track is bound in from the main tree (agents/isolation.ts), one directory for every conversation, because a
|
|
867
|
-
* transcript, a ledger, a browser capture or a staged doc written into a per-worktree copy is simply lost.
|
|
868
|
-
*
|
|
869
|
-
* The two used to be one bind over the whole dir, with the tracked slice sparse-excluded from every worktree to
|
|
870
|
-
* keep git from writing through it. That put the ONE thing a person reviews outside the one door that records
|
|
871
|
-
* provenance: an agent's settings edit, approval, environment fragment or skill went straight into the owner's
|
|
872
|
-
* working tree, unattributed, with no branch commit and nothing for a land to conflict on. Binding by group
|
|
873
|
-
* ends both problems at once, nothing tracked sits behind a bind, so nothing git does in a worktree can reach
|
|
874
|
-
* the live tree, and the sparse machinery has nothing left to guard.
|
|
875
|
-
*
|
|
876
|
-
* WHOLE GROUP DIRS WHERE THE WHOLE GROUP IS UNTRACKED (records, local, identity, secrets), not their entries: a
|
|
877
|
-
* file an extension writes under `records/` without declaring it must still land in the shared tree, and a
|
|
878
|
-
* per-entry bind would strand it in the worktree. Only a group that MIXES tracked and untracked entries (config,
|
|
879
|
-
* for the staged docs tree) is bound entry by entry. Derived, so a store added tomorrow is placed by its
|
|
880
|
-
* `versioned` flag alone, and the layout guard in workspace-state.test.ts pins that no tracked entry can ever
|
|
881
|
-
* sit under a shared prefix. Trailing slash kept on every entry, as the table spells directories. */
|
|
882
|
-
export const SHARED_STATE_PATHS: readonly string[] = STATE_GROUPS.flatMap((group) => {
|
|
883
|
-
const files = WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group);
|
|
884
|
-
return files.some((file) => file.versioned === true)
|
|
885
|
-
? files.filter((file) => file.versioned !== true).map((file) => file.path)
|
|
886
|
-
: [`${STATE_GROUP_DIR[group]}/`];
|
|
887
|
-
});
|
|
888
|
-
|
|
889
|
-
/* THE SLICE DESKTOP-SYNC COPIES DOWN, ordinary state and the records that bind this sandbox to its owner,
|
|
890
|
-
* minus anything that opted out (see `backup` on the interface).
|
|
891
|
-
*
|
|
892
|
-
* The sync used to ignore `.intentic` WHOLE, which is the same conflation the `backup` flag exists to undo: the
|
|
893
|
-
* dir holds credentials, so the dir was excluded, so a sandbox going away also took every persona, skill,
|
|
894
|
-
* automation, draft and transcript the owner had. This is the list that makes the owner's machine an actual
|
|
895
|
-
* backup instead of a copy of the source tree only.
|
|
896
|
-
*
|
|
897
|
-
* It is deliberately NOT the same as the export bundle. A bundle asks what may be reconstituted somewhere else;
|
|
898
|
-
* this asks what the owner may keep. `ownership` is the entries where those differ, and it is in here. */
|
|
899
|
-
export const BACKED_UP_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter(
|
|
900
|
-
(file) => file.backup !== false && (file.portability === "carry" || file.portability === "identity"),
|
|
901
|
-
).map((file) => file.path);
|
|
902
|
-
|
|
903
|
-
/* Its complement, which is what a sync ignore list actually needs: everything under the state dir that must NOT
|
|
904
|
-
* come down. Derived from the same predicate rather than listed, so a store added tomorrow is excluded until its
|
|
905
|
-
* class says otherwise, the same default-deny the search floor and the portability classes are built on. */
|
|
906
|
-
export const UNBACKED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => !BACKED_UP_STATE_PATHS.includes(file.path)).map(
|
|
907
|
-
(file) => file.path,
|
|
908
|
-
);
|
|
909
|
-
|
|
910
|
-
/* THE ONE WAY AN EXTENSION NAMES ITS SCRATCH HOME, `.intentic/runtime/extensions/<id>`, workspace-relative
|
|
911
|
-
* and forward-slash so the browser bundle can hold it too; callers join it onto whatever root is in force.
|
|
912
|
-
*
|
|
913
|
-
* It exists for the reason statePath does one table over: before it, every gateway spelled the layout itself
|
|
914
|
-
* and one extension (deployments) simply didn't, minting `komodo.json` at the `.intentic` root where nothing
|
|
915
|
-
* classified it. An extension that composes through this helper cannot land outside its own directory, so the
|
|
916
|
-
* runtime/ entry's `derived` covers whatever it writes tomorrow. Extension ids are validated slugs already;
|
|
917
|
-
* the replace is defence in depth against a path ever being built from something else. */
|
|
918
|
-
export const extensionRuntimeDir = (extension: string): string =>
|
|
919
|
-
`${STATE_GROUP_DIR.local}/runtime/extensions/${extension.replaceAll(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
920
|
-
|
|
921
|
-
/* The manifests whose problems the unreadable-manifest notice SHOWS, the handful a person hand-edits, and the
|
|
922
|
-
* one fact that decides it is already in the table above.
|
|
923
|
-
*
|
|
924
|
-
* Every store reads through the same `jsonFile`, so every store reports what it could not make sense of, and for
|
|
925
|
-
* a long time the notice showed all of them. That is wrong twice over. Its advice, fix the file and this clears
|
|
926
|
-
* on its own, is addressed to somebody holding an editor, which is true of `settings.json` and false of a
|
|
927
|
-
* daemon-written LEDGER nobody opens: a run history that stopped matching a schema the build tightened is not a
|
|
928
|
-
* mistake the owner made, and the card asked them to repair sixty kilobytes of machine JSON by hand. Worse, a
|
|
929
|
-
* file that reports into the notice without feeding the notice's QUERY leaves a complaint no write can refresh,
|
|
930
|
-
* so it sits on screen until the daemon restarts, which is exactly how the workflow ledger's entry became
|
|
931
|
-
* permanent furniture.
|
|
932
|
-
*
|
|
933
|
-
* Both follow from one rule, which is why this derives rather than lists: a file's problems are shown IFF a write
|
|
934
|
-
* to that file refreshes the notice. Declaring `manifests` in `invalidates` is the entire opt-in, so the edit
|
|
935
|
-
* that puts a file on the card is the same edit that keeps it current, and neither can be done without the
|
|
936
|
-
* other. A ledger that breaks still falls back and still sets its unreadable bytes aside on the next write
|
|
937
|
-
* (store/json-file.ts), it just stops asking the owner to fix it. */
|
|
938
|
-
export const REPORTED_MANIFEST_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.invalidates.includes("manifests")).map(
|
|
939
|
-
(file) => file.path,
|
|
940
|
-
);
|
|
941
|
-
|
|
942
|
-
// Accepts either separator, like isLockedWorkspacePath below: the daemon holds these as platform paths and makes
|
|
943
|
-
// them relative at the last moment, and normalizing at each call site is the one that eventually gets forgotten.
|
|
944
|
-
export const isReportedManifest = (relPath: string): boolean => REPORTED_MANIFEST_PATHS.includes(relPath.replaceAll("\\", "/"));
|
|
945
|
-
|
|
946
|
-
/* THE DAEMON'S OWN CONTROL PLANE, the entries directly under the workspace root's `.intentic/` that the file
|
|
947
|
-
* API refuses to read, write, move or delete for anyone, the owner included (workspace/workspace-files.ts holds
|
|
948
|
-
* the enforcement and the full reasoning for each name).
|
|
949
|
-
*
|
|
950
|
-
* The list lives HERE, in the package both sides import, because the browser has to draw the same rule the
|
|
951
|
-
* daemon enforces. It didn't, and the gap was a small piece of theatre: the explorer listed `capabilities.json`
|
|
952
|
-
* like any other file, opening it flashed a tab, the read came back with nothing there, and the tab closed
|
|
953
|
-
* itself, a refusal acted out as a glitch. A file the app will not open should say so before it is clicked,
|
|
954
|
-
* which takes a rule the explorer can consult, not a status code it can only react to.
|
|
955
|
-
*
|
|
956
|
-
* Naming these to the browser gives nothing away that the tree did not already publish, it listed them, sizes
|
|
957
|
-
* and all. What stays behind the guard is the only thing that ever mattered: the bytes. */
|
|
958
|
-
/* GROUP-RELATIVE NOW, and the one rule the regrouping did NOT simplify, worth saying because every other rule
|
|
959
|
-
* over this tree collapsed to a prefix and this one could not. What the file API refuses to open cuts ACROSS the
|
|
960
|
-
* groups: the capability manifest is `config`, the transcripts are `records`, the browser profiles are `local`,
|
|
961
|
-
* and all of `identity` and `secrets` is in. That is not an accident of the grouping, it is a different question
|
|
962
|
-
*, "would showing the bytes hand someone something" rather than "what kind of thing is this", so it keeps an
|
|
963
|
-
* explicit list, just one that now names the folder each entry lives in. */
|
|
964
|
-
export const LOCKED_STATE_ENTRIES: ReadonlySet<string> = new Set([
|
|
965
|
-
"identity/owner.json",
|
|
966
|
-
"identity/members.json",
|
|
967
|
-
"identity/control-tokens.json",
|
|
968
|
-
"config/capabilities.json",
|
|
969
|
-
"secrets/ci.json",
|
|
970
|
-
"secrets/auth",
|
|
971
|
-
"records/sessions",
|
|
972
|
-
"local/browser",
|
|
973
|
-
/* The provider CLI's own home, which this table does not declare and so has no group to move into, it is
|
|
974
|
-
* written by the agent's runtime rather than by any daemon store. It stays at the state dir's root, and the
|
|
975
|
-
* two-segment match below still reaches it because a bare name joins to itself. Locked for the reason the
|
|
976
|
-
* credential entries are: it holds a live session for whatever the agent is signed into. */
|
|
977
|
-
"claude.json",
|
|
978
|
-
]);
|
|
979
|
-
|
|
980
|
-
/* WHERE THE CLI'S PLAN FILES LAND, workspace-relative — and the one thing inside a locked entry that is not
|
|
981
|
-
* the sandbox's own state, which is why it is declared here rather than beside the card that draws it.
|
|
982
|
-
*
|
|
983
|
-
* `~/.claude/plans` is a symlink onto this directory (sessions/session-store.ts links the SDK's conversation
|
|
984
|
-
* state onto the workspace volume), so a plan file has a HARNESS-OWNED address: no guessing whether prose is a
|
|
985
|
-
* plan, no threshold on length, the path says so.
|
|
986
|
-
*
|
|
987
|
-
* What lands there is a DOCUMENT ADDRESSED TO THE READER. `records/sessions` is locked because it holds the
|
|
988
|
-
* provider's own conversation state; a plan is the opposite of that — the chat renders its full text into the
|
|
989
|
-
* card asking the reader to approve it, so opening the file publishes nothing the transcript had not. Locked
|
|
990
|
-
* anyway, the one link the card offers into the workspace landed on a padlock reading "it holds something only
|
|
991
|
-
* the sandbox itself uses", about a document the sandbox had just asked the reader to approve. */
|
|
992
|
-
export const PLAN_DOCUMENTS_DIR = `${STATE_DIR}/records/sessions/claude/plans`;
|
|
993
|
-
|
|
994
|
-
/* WHICH locked entry a workspace-root-relative path belongs to, or undefined for a path that is not in the
|
|
995
|
-
* control plane at all. Scoped deliberately tight, matching the guard: only the ROOT `.intentic` counts (a
|
|
996
|
-
* repo's own nested one is ordinary content) and only these entries within it, subtrees included, so a new
|
|
997
|
-
* provider dropped under `auth/` is covered without a second edit.
|
|
998
|
-
*
|
|
999
|
-
* The ROOT's own `.git` joins them. It is the pointer to the shadow history repo kept off the workspace so the
|
|
1000
|
-
* agent cannot rewrite its own past; a NESTED repo's `.git` is ordinary content and stays browsable.
|
|
1001
|
-
*
|
|
1002
|
-
* The ENTRY rather than a boolean, because the screen that reports a refusal has to say what the file holds and
|
|
1003
|
-
* where the thing inside it is actually managed, and it can only do that from the name of the entry the path
|
|
1004
|
-
* matched — never from the leaf, which is a Chromium cookie jar or a mint-fresh session id. Keeping that lookup
|
|
1005
|
-
* keyed on this function's answer is what stops the browser's sentences from drifting off the daemon's list, as
|
|
1006
|
-
* they did through the regrouping: every one of them was still keyed on `sessions` and `auth` while the rule
|
|
1007
|
-
* had moved to `records/sessions` and `secrets/auth`, so every locked file in the product fell through to the
|
|
1008
|
-
* generic sentence and lost its way out.
|
|
1009
|
-
*
|
|
1010
|
-
* Accepts either slash so a caller holding a platform path doesn't have to normalize first. */
|
|
1011
|
-
export const lockedWorkspaceEntry = (relPath: string): string | undefined => {
|
|
1012
|
-
const segments = relPath.split(/[\\/]/).filter((segment) => segment !== "" && segment !== ".");
|
|
1013
|
-
if (segments[0] === ".git") {
|
|
1014
|
-
return ".git";
|
|
1015
|
-
}
|
|
1016
|
-
if (segments[0] !== STATE_DIR) {
|
|
1017
|
-
return undefined;
|
|
1018
|
-
}
|
|
1019
|
-
const rel = segments.join("/");
|
|
1020
|
-
if (rel === PLAN_DOCUMENTS_DIR || rel.startsWith(`${PLAN_DOCUMENTS_DIR}/`)) {
|
|
1021
|
-
return undefined;
|
|
1022
|
-
}
|
|
1023
|
-
// Two segments, which covers both spellings in the set above: a grouped entry (`secrets/auth`) matches as
|
|
1024
|
-
// written, and a bare root entry (`claude.json`) joins to itself because there is no second segment to add.
|
|
1025
|
-
const entry = segments.slice(1, 3).join("/");
|
|
1026
|
-
return LOCKED_STATE_ENTRIES.has(entry) ? entry : undefined;
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
|
-
// Whether a path lands in that control plane, and so is refused by the file API and shown locked rather than
|
|
1030
|
-
// opened. The question every guard asks; the entry above is for the one screen that has to name it.
|
|
1031
|
-
export const isLockedWorkspacePath = (relPath: string): boolean => lockedWorkspaceEntry(relPath) !== undefined;
|
|
1032
|
-
|
|
1033
|
-
/* THE LOCKED ENTRIES THE ROOT REPO TRACKS, refused by the file API, and diffable anyway.
|
|
1034
|
-
*
|
|
1035
|
-
* `capabilities.json` is the only one today and the whole reason this exists. Both of its rules are right on
|
|
1036
|
-
* their own: it is `versioned`, because connecting this sandbox to a deployment orchestrator is the largest
|
|
1037
|
-
* change anyone makes to what it can DO and that belongs in review; and it is locked, because a member who
|
|
1038
|
-
* could PUT one through the generic file API would be granting themselves a capability the owner never
|
|
1039
|
-
* approved. The lock was always about that WRITE, its credentials live in the vault, not in the file.
|
|
1040
|
-
*
|
|
1041
|
-
* Together, though, the second silently cancelled the first. The Changes panel listed the file (git tracks it,
|
|
1042
|
-
* so `git status` reports it), and clicking the row asked a diff route that refuses every control-plane path,
|
|
1043
|
-
* a 404 on the one surface `versioned` exists to produce. The bytes were already in `git log`, in every clone
|
|
1044
|
-
* of the root repo and in the workspace search; only the review was missing.
|
|
1045
|
-
*
|
|
1046
|
-
* So the review surfaces ask THIS instead of the flat lock, and it derives from the same flag rather than
|
|
1047
|
-
* naming the file, so marking another locked entry `versioned` cannot reproduce the contradiction. Every other
|
|
1048
|
-
* surface, read, write, move, delete, publish, still asks `isLockedWorkspacePath` and still refuses.
|
|
1049
|
-
*
|
|
1050
|
-
* Accepts either slash, like the rule above it. */
|
|
1051
|
-
export const isReviewableLockedPath = (relPath: string): boolean => {
|
|
1052
|
-
const rel = relPath.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
1053
|
-
return isLockedWorkspacePath(rel) && VERSIONED_STATE_PATHS.some((path) => (path.endsWith("/") ? rel.startsWith(path) : rel === path));
|
|
1054
|
-
};
|
|
1055
|
-
|
|
1056
|
-
/* Every path this table declares, as a type. `as const` above is what makes it one, and it is what finally makes
|
|
1057
|
-
* the first sentence of this file's header TRUE rather than aspirational.
|
|
1058
|
-
*
|
|
1059
|
-
* "The daemon builds its store paths from `path`" was the design; the code did not. `composition.ts` and twenty
|
|
1060
|
-
* files beside it spelled the same layout a SECOND way, `join(root, ".intentic", "settings.json")`, with
|
|
1061
|
-
* nothing tying the two spellings together. Rename a store's file and this table keeps declaring the old name:
|
|
1062
|
-
* no error, no failing test, just a view that quietly stops refreshing, which is the exact failure the table was
|
|
1063
|
-
* written to end and the exact way approvals went missing.
|
|
1064
|
-
*
|
|
1065
|
-
* So the daemon joins through `statePath` (workspace/state-paths.ts), which takes one of THESE and nothing else.
|
|
1066
|
-
* A rename is now a compile error at every site that names the file, in both packages, or it is not a rename. */
|
|
1067
|
-
export type WorkspaceStatePath = (typeof STATE_FILES)[number]["path"];
|
|
1068
|
-
|
|
1069
|
-
/* The query keys a batch of changed paths makes stale, deduped and stable. The browser's `/events` handler calls
|
|
1070
|
-
* this; keeping it here rather than in the web means the rule is unit-testable without a query client, and the
|
|
1071
|
-
* daemon can assert against the same table.
|
|
1072
|
-
*
|
|
1073
|
-
* `contributed` is what the ACTIVATED extensions declared in `contributes.files`, passed in rather than
|
|
1074
|
-
* imported, because which extensions are live is a browser fact this package has no way to know. It is a
|
|
1075
|
-
* required argument for the same reason: an added second source that callers may forget is a source that
|
|
1076
|
-
* silently does nothing, which is the failure this whole file exists to remove. Extension entries are unioned
|
|
1077
|
-
* flat with the core ones, not layered over them: both lists describe the same fact about the same file, and a
|
|
1078
|
-
* path can legitimately match one entry in each, a core prefix that invalidates nothing must not veto a
|
|
1079
|
-
* narrower extension entry beneath it, or everything under one of the daemon's machine-state prefixes would be
|
|
1080
|
-
* unreachable to extensions by construction. */
|
|
1081
|
-
export const staleQueryKeys = (paths: readonly string[], contributed: readonly FileContribution[]): readonly string[] => [
|
|
1082
|
-
...new Set(
|
|
1083
|
-
[...WORKSPACE_STATE_FILES, ...contributed]
|
|
1084
|
-
.filter((file) => file.invalidates.length > 0 && paths.some((path) => path.startsWith(file.path)))
|
|
1085
|
-
.flatMap((file) => file.invalidates),
|
|
1086
|
-
),
|
|
1087
|
-
];
|
|
1088
|
-
|
|
1089
|
-
/* Every query key any watched file feeds, what a NEW /events connection invalidates wholesale (core's table
|
|
1090
|
-
* plus the running extensions'). The file push is these keys' ONLY live feed, and a `workspaceChanged` frame
|
|
1091
|
-
* produced while the stream was down is a frame nobody will ever resend, so each key's view would sit stale
|
|
1092
|
-
* until the file's NEXT write, indefinitely for anything that settled while the browser was away. Re-asking on
|
|
1093
|
-
* connect bounds the damage at one cheap read per key, which is what lets those views go entirely unpolled. */
|
|
1094
|
-
export const fileBoundQueryKeys = (contributed: readonly FileContribution[]): readonly string[] => [
|
|
1095
|
-
...new Set([...WORKSPACE_STATE_FILES, ...contributed].flatMap((file) => file.invalidates)),
|
|
1096
|
-
];
|