@intentic/sandbox-contract 1.176.3 → 1.209.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 +65 -0
- package/dist/agent-catalog.d.ts +15 -2
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +50 -1
- package/dist/agent-catalog.js.map +1 -1
- package/dist/agent-run-model.d.ts +3 -0
- package/dist/agent-run-model.d.ts.map +1 -0
- package/dist/agent-run-model.js +10 -0
- package/dist/agent-run-model.js.map +1 -0
- package/dist/capability-env.d.ts +2 -0
- package/dist/capability-env.d.ts.map +1 -0
- package/dist/capability-env.js +2 -0
- package/dist/capability-env.js.map +1 -0
- package/dist/chores/chores.d.ts +9 -0
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js +257 -18
- package/dist/chores/chores.js.map +1 -1
- package/dist/chores/digest.js +0 -0
- package/dist/chores/digest.js.map +1 -1
- package/dist/chores/extension-update.d.ts +9 -0
- package/dist/chores/extension-update.d.ts.map +1 -0
- package/dist/chores/extension-update.js +15 -0
- package/dist/chores/extension-update.js.map +1 -0
- package/dist/chores/fix-deps.d.ts +10 -0
- package/dist/chores/fix-deps.d.ts.map +1 -0
- package/dist/chores/fix-deps.js +18 -0
- package/dist/chores/fix-deps.js.map +1 -0
- package/dist/chores/index.d.ts +7 -2
- package/dist/chores/index.d.ts.map +1 -1
- package/dist/chores/index.js +4 -1
- package/dist/chores/index.js.map +1 -1
- package/dist/chores/probes.d.ts.map +1 -1
- package/dist/chores/probes.js +127 -3
- package/dist/chores/probes.js.map +1 -1
- package/dist/chores/stack.d.ts +27 -0
- package/dist/chores/stack.d.ts.map +1 -0
- package/dist/chores/stack.js +121 -0
- package/dist/chores/stack.js.map +1 -0
- package/dist/chores/verdict.d.ts +2 -1
- package/dist/chores/verdict.d.ts.map +1 -1
- package/dist/chores/verdict.js +53 -6
- package/dist/chores/verdict.js.map +1 -1
- package/dist/contract-lock.d.ts +3 -0
- package/dist/contract-lock.d.ts.map +1 -0
- package/dist/contract-lock.js +35 -0
- package/dist/contract-lock.js.map +1 -0
- package/dist/contracts/activity.contract.d.ts +10 -0
- package/dist/contracts/activity.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.d.ts +230 -20
- 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 +847 -1
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +3 -1
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/automations.contract.d.ts +89 -0
- package/dist/contracts/automations.contract.d.ts.map +1 -1
- package/dist/contracts/automations.contract.js +3 -1
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +108 -32
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/capabilities.contract.js +5 -1
- package/dist/contracts/capabilities.contract.js.map +1 -1
- package/dist/contracts/chores.contract.d.ts +43 -0
- package/dist/contracts/chores.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.d.ts +5 -0
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.js +2 -2
- package/dist/contracts/ci.contract.js.map +1 -1
- package/dist/contracts/claude.contract.d.ts +3 -14
- package/dist/contracts/claude.contract.d.ts.map +1 -1
- package/dist/contracts/claude.contract.js +2 -3
- package/dist/contracts/claude.contract.js.map +1 -1
- package/dist/contracts/drafts.contract.d.ts +4 -0
- package/dist/contracts/drafts.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts +28 -12
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js +9 -0
- package/dist/contracts/endpoints.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts +399 -69
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js +15 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/git.contract.d.ts +209 -11
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +12 -2
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/grok.contract.d.ts +0 -13
- package/dist/contracts/grok.contract.d.ts.map +1 -1
- package/dist/contracts/grok.contract.js +1 -2
- package/dist/contracts/grok.contract.js.map +1 -1
- package/dist/contracts/host.contract.d.ts +39 -0
- package/dist/contracts/host.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.js +3 -2
- package/dist/contracts/host.contract.js.map +1 -1
- package/dist/contracts/loops.contract.d.ts +343 -0
- package/dist/contracts/loops.contract.d.ts.map +1 -0
- package/dist/contracts/loops.contract.js +11 -0
- package/dist/contracts/loops.contract.js.map +1 -0
- package/dist/contracts/panels.contract.d.ts +6 -0
- package/dist/contracts/panels.contract.d.ts.map +1 -1
- package/dist/contracts/personas.contract.d.ts +112 -0
- package/dist/contracts/personas.contract.d.ts.map +1 -0
- package/dist/contracts/personas.contract.js +13 -0
- package/dist/contracts/personas.contract.js.map +1 -0
- package/dist/contracts/ports.contract.d.ts +1 -0
- package/dist/contracts/ports.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.d.ts +1 -0
- package/dist/contracts/prepush.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.js.map +1 -1
- package/dist/contracts/{codex.contract.d.ts → providers.contract.d.ts} +11 -3
- package/dist/contracts/providers.contract.d.ts.map +1 -0
- package/dist/contracts/providers.contract.js +6 -0
- package/dist/contracts/providers.contract.js.map +1 -0
- package/dist/contracts/public.contract.d.ts +24 -0
- package/dist/contracts/public.contract.d.ts.map +1 -0
- package/dist/contracts/public.contract.js +8 -0
- package/dist/contracts/public.contract.js.map +1 -0
- package/dist/contracts/push.contract.d.ts +3 -3
- package/dist/contracts/secrets.contract.d.ts +9 -0
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/sessions.contract.d.ts +16 -1
- 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 +352 -58
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js +2 -1
- package/dist/contracts/settings.contract.js.map +1 -1
- package/dist/contracts/share.contract.d.ts +55 -0
- package/dist/contracts/share.contract.d.ts.map +1 -0
- package/dist/contracts/share.contract.js +9 -0
- package/dist/contracts/share.contract.js.map +1 -0
- package/dist/contracts/skills.contract.d.ts +41 -0
- package/dist/contracts/skills.contract.d.ts.map +1 -0
- package/dist/contracts/skills.contract.js +9 -0
- package/dist/contracts/skills.contract.js.map +1 -0
- package/dist/contracts/system.contract.d.ts +204 -8
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +10 -2
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/contracts/workflows.contract.d.ts +575 -0
- package/dist/contracts/workflows.contract.d.ts.map +1 -0
- package/dist/contracts/workflows.contract.js +13 -0
- package/dist/contracts/workflows.contract.js.map +1 -0
- package/dist/contracts/workspace.contract.d.ts +18 -4
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/contracts/workspace.contract.js +6 -3
- package/dist/contracts/workspace.contract.js.map +1 -1
- package/dist/conversation-ids.d.ts +2 -0
- package/dist/conversation-ids.d.ts.map +1 -0
- package/dist/conversation-ids.js +113 -0
- package/dist/conversation-ids.js.map +1 -0
- package/dist/events.d.ts +523 -17
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +106 -13
- package/dist/events.js.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +10 -0
- package/dist/history-state.js.map +1 -1
- package/dist/hostnames.d.ts +4 -0
- package/dist/hostnames.d.ts.map +1 -1
- package/dist/hostnames.js +7 -2
- package/dist/hostnames.js.map +1 -1
- package/dist/index.d.ts +3791 -478
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -17
- package/dist/index.js.map +1 -1
- package/dist/listener-protocol.d.ts +77 -0
- package/dist/listener-protocol.d.ts.map +1 -0
- package/dist/listener-protocol.js +33 -0
- package/dist/listener-protocol.js.map +1 -0
- package/dist/model-order.d.ts +1 -0
- package/dist/model-order.d.ts.map +1 -1
- package/dist/model-order.js +16 -0
- package/dist/model-order.js.map +1 -1
- package/dist/output-fields.d.ts +30 -0
- package/dist/output-fields.d.ts.map +1 -0
- package/dist/output-fields.js +57 -0
- package/dist/output-fields.js.map +1 -0
- package/dist/path-refs.d.ts.map +1 -1
- package/dist/path-refs.js.map +1 -1
- package/dist/publish-drafts.d.ts +7 -0
- package/dist/publish-drafts.d.ts.map +1 -0
- package/dist/publish-drafts.js +20 -0
- package/dist/publish-drafts.js.map +1 -0
- package/dist/quick-model.d.ts +2 -1
- package/dist/quick-model.d.ts.map +1 -1
- package/dist/quick-model.js +18 -14
- package/dist/quick-model.js.map +1 -1
- package/dist/routes.d.ts +3 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +63 -0
- package/dist/routes.js.map +1 -1
- package/dist/runtime-state.d.ts +33 -0
- package/dist/runtime-state.d.ts.map +1 -0
- package/dist/runtime-state.js +14 -0
- package/dist/runtime-state.js.map +1 -0
- package/dist/schemas.d.ts +4886 -851
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +993 -192
- package/dist/schemas.js.map +1 -1
- package/dist/search-globs.d.ts +6 -0
- package/dist/search-globs.d.ts.map +1 -0
- package/dist/search-globs.js +39 -0
- package/dist/search-globs.js.map +1 -0
- package/dist/share-paths.d.ts +8 -0
- package/dist/share-paths.d.ts.map +1 -0
- package/dist/share-paths.js +21 -0
- package/dist/share-paths.js.map +1 -0
- package/dist/title.d.ts.map +1 -1
- package/dist/title.js +1 -1
- package/dist/title.js.map +1 -1
- package/dist/tunnel-ids.d.ts +1 -0
- package/dist/tunnel-ids.d.ts.map +1 -1
- package/dist/tunnel-ids.js +1 -0
- package/dist/tunnel-ids.js.map +1 -1
- package/dist/versions.d.ts +4 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +15 -0
- package/dist/versions.js.map +1 -0
- package/dist/workflow-faults.d.ts +4 -0
- package/dist/workflow-faults.d.ts.map +1 -0
- package/dist/workflow-faults.js +115 -0
- package/dist/workflow-faults.js.map +1 -0
- package/dist/workspace-state.d.ts +280 -1
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +163 -21
- package/dist/workspace-state.js.map +1 -1
- package/package.json +30 -6
- package/src/agent-catalog.test.ts +147 -7
- package/src/agent-catalog.ts +233 -21
- package/src/agent-run-model.test.ts +60 -0
- package/src/agent-run-model.ts +51 -0
- package/src/capability-env.ts +10 -0
- package/src/capability-ledger.test.ts +110 -0
- package/src/chores/chores.test.ts +32 -0
- package/src/chores/chores.ts +456 -32
- package/src/chores/digest.ts +0 -0
- package/src/chores/extension-update.ts +37 -0
- package/src/chores/fix-deps.ts +40 -0
- package/src/chores/index.ts +7 -2
- package/src/chores/probes.test.ts +155 -3
- package/src/chores/probes.ts +200 -4
- package/src/chores/stack.test.ts +126 -0
- package/src/chores/stack.ts +244 -0
- package/src/chores/verdict.test.ts +357 -19
- package/src/chores/verdict.ts +95 -21
- package/src/contract-lock.test.ts +17 -0
- package/src/contract-lock.ts +66 -0
- package/src/contracts/agent.contract.ts +6 -0
- package/src/contracts/agents.contract.ts +12 -0
- package/src/contracts/automations.contract.ts +17 -1
- package/src/contracts/capabilities.contract.ts +22 -0
- package/src/contracts/ci.contract.ts +10 -2
- package/src/contracts/claude.contract.ts +8 -4
- package/src/contracts/endpoints.contract.ts +21 -0
- package/src/contracts/extensions.contract.ts +42 -0
- package/src/contracts/git.contract.ts +33 -6
- package/src/contracts/grok.contract.ts +4 -3
- package/src/contracts/host.contract.ts +13 -2
- package/src/contracts/loops.contract.ts +62 -0
- package/src/contracts/personas.contract.ts +56 -0
- package/src/contracts/prepush.contract.ts +4 -3
- package/src/contracts/providers.contract.ts +23 -0
- package/src/contracts/public.contract.ts +14 -0
- package/src/contracts/sessions.contract.ts +5 -1
- package/src/contracts/settings.contract.ts +5 -0
- package/src/contracts/share.contract.ts +20 -0
- package/src/contracts/skills.contract.ts +24 -0
- package/src/contracts/system.contract.ts +27 -3
- package/src/contracts/workflows.contract.ts +78 -0
- package/src/contracts/workspace.contract.ts +10 -2
- package/src/conversation-ids.test.ts +25 -0
- package/src/conversation-ids.ts +160 -0
- package/src/events.test.ts +20 -1
- package/src/events.ts +404 -43
- package/src/history-state.ts +30 -1
- package/src/hostnames.ts +20 -6
- package/src/index.ts +58 -17
- package/src/listener-protocol.ts +96 -0
- package/src/model-order.test.ts +32 -1
- package/src/model-order.ts +56 -3
- package/src/output-fields.ts +111 -0
- package/src/path-refs.test.ts +4 -4
- package/src/path-refs.ts +5 -5
- package/src/publish-drafts.ts +59 -0
- package/src/quick-model.test.ts +70 -27
- package/src/quick-model.ts +76 -40
- package/src/routes.test.ts +91 -3
- package/src/routes.ts +135 -0
- package/src/runtime-state.test.ts +45 -0
- package/src/runtime-state.ts +124 -0
- package/src/schemas.test.ts +16 -29
- package/src/schemas.ts +3475 -552
- package/src/search-globs.test.ts +46 -0
- package/src/search-globs.ts +76 -0
- package/src/share-paths.test.ts +48 -0
- package/src/share-paths.ts +68 -0
- package/src/state-portability.ts +8 -8
- package/src/title.test.ts +20 -1
- package/src/title.ts +12 -3
- package/src/tunnel-ids.ts +15 -1
- package/src/versions.test.ts +39 -0
- package/src/versions.ts +48 -0
- package/src/workflow-faults.test.ts +127 -0
- package/src/workflow-faults.ts +188 -0
- package/src/workspace-state.test.ts +169 -15
- package/src/workspace-state.ts +427 -35
- package/dist/contracts/codex.contract.d.ts.map +0 -1
- package/dist/contracts/codex.contract.js +0 -6
- package/dist/contracts/codex.contract.js.map +0 -1
- package/dist/contracts/gemini.contract.d.ts +0 -16
- package/dist/contracts/gemini.contract.d.ts.map +0 -1
- package/dist/contracts/gemini.contract.js +0 -6
- package/dist/contracts/gemini.contract.js.map +0 -1
- package/dist/contracts/kimi.contract.d.ts +0 -16
- package/dist/contracts/kimi.contract.d.ts.map +0 -1
- package/dist/contracts/kimi.contract.js +0 -6
- package/dist/contracts/kimi.contract.js.map +0 -1
- package/dist/contracts/komodo.contract.d.ts +0 -125
- package/dist/contracts/komodo.contract.d.ts.map +0 -1
- package/dist/contracts/komodo.contract.js +0 -14
- package/dist/contracts/komodo.contract.js.map +0 -1
- package/dist/contracts/memory.contract.d.ts +0 -34
- package/dist/contracts/memory.contract.d.ts.map +0 -1
- package/dist/contracts/memory.contract.js +0 -9
- package/dist/contracts/memory.contract.js.map +0 -1
- package/src/contracts/codex.contract.ts +0 -10
- package/src/contracts/gemini.contract.ts +0 -11
- package/src/contracts/kimi.contract.ts +0 -9
- package/src/contracts/komodo.contract.ts +0 -36
- package/src/contracts/memory.contract.ts +0 -13
package/src/workspace-state.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { STATE_DIR } from "@intentic/constants";
|
|
2
|
+
import type { FileContribution } from "@intentic/extension-manifest";
|
|
2
3
|
import type { StateFile } from "./state-portability.js";
|
|
3
4
|
|
|
4
5
|
/* WHICH WORKSPACE FILE BACKS WHICH CORE VIEW — one declaration, read by both sides of the wire.
|
|
@@ -49,9 +50,48 @@ export interface WorkspaceStateFile extends StateFile {
|
|
|
49
50
|
readonly invalidates: readonly string[];
|
|
50
51
|
// Why this file has no invalidations, for the entries that declare none. Absent when it has some.
|
|
51
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
|
+
* Only CONFIGURATION belongs here — the small, slow-moving files that decide how this sandbox behaves. Two
|
|
64
|
+
* kinds of entry are excluded on purpose even though they are `carry` and hold no secret:
|
|
65
|
+
* - LEDGERS (workflow runs, loop iterations, thread bookkeeping, permission-usage batches), which are
|
|
66
|
+
* rewritten on a timer or several times per step. Tracking them buries the owner's code review under
|
|
67
|
+
* machine noise — one of them is written every few seconds while a browser has the app open.
|
|
68
|
+
* - BULK (session transcripts, artifacts), which are hundreds of megabytes of constantly-rewritten
|
|
69
|
+
* content. They travel in a bundle; they do not belong in a diff.
|
|
70
|
+
* `versioned` is therefore NARROWER than `carry`, and the two answer different questions: carry is "does it
|
|
71
|
+
* move to a new sandbox", this is "should a human review it changing". */
|
|
72
|
+
readonly versioned?: true;
|
|
73
|
+
/* AUTHORED but not configuration — the fourth question an entry can answer, and the narrowest: is this
|
|
74
|
+
* human- or agent-written TEXT that a workspace search should surface? Every `versioned` entry already is
|
|
75
|
+
* (a setting, a persona, a skill — things the agent is asked to find and edit), so this flag exists only
|
|
76
|
+
* for the entries that are authored content without being config: a draft awaiting approval, a staged
|
|
77
|
+
* README, an extension the agent wrote in place. Everything else under `.intentic` is machine state, and
|
|
78
|
+
* `SEARCHABLE_STATE_PATHS` below is what lets the search engine deny the rest BY DEFAULT instead of
|
|
79
|
+
* hand-keeping a deny list that goes stale the day a store is added (which is how a 98 kB loop ledger and
|
|
80
|
+
* whole third-party extension checkouts ended up ranking in code search). */
|
|
81
|
+
readonly authored?: true;
|
|
82
|
+
/* WHO BUILDS THIS TREE, when it is not the daemon — an extension, pnpm, another process entirely. Declared
|
|
83
|
+
* on the entry because the coverage guard's second direction ("every declared entry is built somewhere in
|
|
84
|
+
* the daemon") is only meaningful for entries the daemon owns: one it can never build must say who does, or
|
|
85
|
+
* the guard would read the entry as dead. Absent for everything the daemon writes itself. */
|
|
86
|
+
readonly outsideWriter?: string;
|
|
52
87
|
}
|
|
53
88
|
|
|
54
|
-
|
|
89
|
+
/* Declared `as const` so the paths survive as literal types (see WorkspaceStatePath below), then published under
|
|
90
|
+
* the interface. Both bindings are needed and neither is redundant: the const is the only thing that can produce
|
|
91
|
+
* the path union, and every consumer reads entries as `WorkspaceStateFile` — an exact-literal tuple loses the
|
|
92
|
+
* optional members (`note`, `why`) on the entries that omit them, which is a worse type for reading than the
|
|
93
|
+
* interface it satisfies. One list, two views of it. */
|
|
94
|
+
const STATE_FILES = [
|
|
55
95
|
/* A capability add/remove recomposes the environment overlay and can add or drop a repo's panel.
|
|
56
96
|
*
|
|
57
97
|
* Each entry's `config` carries that capability's credential (an mcp server's token, a Komodo key, an ssh
|
|
@@ -59,7 +99,35 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
59
99
|
* fragments from, which makes this the entry where the owner's export choice has the most visible
|
|
60
100
|
* consequence: a bundle exported WITHOUT secrets rebuilds a stock overlay, and the import report has to
|
|
61
101
|
* name every capability the target needs re-added before its environment matches again. */
|
|
62
|
-
{ path: ".intentic/capabilities.json", invalidates: ["capabilities", "environment", "panels"], portability: "secret" },
|
|
102
|
+
{ path: ".intentic/capabilities.json", invalidates: ["capabilities", "environment", "panels", "manifests"], portability: "secret" },
|
|
103
|
+
|
|
104
|
+
/* Which workspace-derived recommendations the owner has said "not needed" to, and the evidence each was
|
|
105
|
+
* declined against. It rides the `capabilities` key because the catalog is what changes when one lands, and
|
|
106
|
+
* it travels because a decision about what this workspace does NOT need is as much the owner's as the
|
|
107
|
+
* connections themselves — an export that dropped it would greet them on the target with the same
|
|
108
|
+
* suggestions they had already dismissed. Holds no credential: it is a card name and a file path. */
|
|
109
|
+
{ path: ".intentic/capability-dismissals.json", invalidates: ["capabilities"], portability: "carry", versioned: true },
|
|
110
|
+
|
|
111
|
+
/* The secret use ledger — one row per moment the agent's exits spent a stored secret (a `{{secret:name}}`
|
|
112
|
+
* reference resolved into a shell command, a value typed into a browser field), joined onto the secrets
|
|
113
|
+
* inventory as each entry's "last used" (sandbox's secrets/secret-uses.ts). Holds names and destinations,
|
|
114
|
+
* never values — which is why it may `carry`: like the automations' run ledger, a use history is about the
|
|
115
|
+
* secrets, and an export that dropped it would arrive claiming none had ever been touched. */
|
|
116
|
+
{ path: ".intentic/secret-uses.json", invalidates: ["secrets"], portability: "carry" },
|
|
117
|
+
|
|
118
|
+
/* The named personas this sandbox shows the outside world — which connected accounts each one speaks for,
|
|
119
|
+
* what a session wearing it may do, where it works (schemas.ts PersonaSchema). It invalidates `capabilities` as well as
|
|
120
|
+
* its own key because a card and the accounts it names are read together everywhere they are shown: connect
|
|
121
|
+
* a second Reddit and the persona list has a new candidate; remove one and a card points at nothing.
|
|
122
|
+
*
|
|
123
|
+
* It is `carry`, and that is the whole design rather than an oversight — a card is a NAME and a list of ids,
|
|
124
|
+
* never a credential, so it travels to a new sandbox in full while the logins it refers to stay behind. What
|
|
125
|
+
* arrives is a workspace that already knows it has a work-reddit and a studio-x, both visibly unconnected,
|
|
126
|
+
* each waiting for one sign-in. It was also the FIRST file under .intentic the root repo tracked, and the
|
|
127
|
+
* argument it was carved out on — a card is configuration, holds no secret, and belongs in review — is the
|
|
128
|
+
* one `versioned` now generalises to the rest of the config slice (personas/personas-store.ts argues it at
|
|
129
|
+
* length, and its reasoning is why the flag exists rather than a second hand-kept list). */
|
|
130
|
+
{ path: ".intentic/personas.json", invalidates: ["personas", "capabilities", "manifests"], portability: "carry", versioned: true },
|
|
63
131
|
|
|
64
132
|
/* The overlay Dockerfile, four files that a single `.intentic/environment.` prefix used to cover. They are
|
|
65
133
|
* split here because they answer PORTABILITY differently while answering invalidation identically, and the
|
|
@@ -71,9 +139,9 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
71
139
|
* not be on (see composeEnvironment's baseImageOf);
|
|
72
140
|
* - the proposal and the per-tool drafts under environment.d/ are the agent's pending requests, which the
|
|
73
141
|
* owner has not answered yet; they travel so the question survives the move. */
|
|
74
|
-
{ path: ".intentic/environment.custom.Dockerfile", invalidates: ["environment"], portability: "carry" },
|
|
75
|
-
{ path: ".intentic/environment.Dockerfile", invalidates: ["environment"], portability: "carry" },
|
|
76
|
-
{ path: ".intentic/environment.d/", invalidates: ["environment"], portability: "carry" },
|
|
142
|
+
{ path: ".intentic/environment.custom.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
143
|
+
{ path: ".intentic/environment.Dockerfile", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
144
|
+
{ path: ".intentic/environment.d/", invalidates: ["environment"], portability: "carry", versioned: true },
|
|
77
145
|
{
|
|
78
146
|
path: ".intentic/environment.approved.Dockerfile",
|
|
79
147
|
invalidates: ["environment"],
|
|
@@ -81,10 +149,20 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
81
149
|
note: "The target composes its own overlay on first boot; rebuild it there to install the tools it names.",
|
|
82
150
|
},
|
|
83
151
|
|
|
84
|
-
{ path: ".intentic/settings.json", invalidates: ["settings"], portability: "carry" },
|
|
152
|
+
{ path: ".intentic/settings.json", invalidates: ["settings", "manifests"], portability: "carry", versioned: true },
|
|
153
|
+
// The rule table's last-fired stamps, beside the rules themselves. `derived` rather than `carry`: it is a
|
|
154
|
+
// record of what happened in THIS sandbox, and carrying it to a fresh one would date every rule to work
|
|
155
|
+
// that machine never did.
|
|
156
|
+
{
|
|
157
|
+
path: ".intentic/rule-firings.json",
|
|
158
|
+
invalidates: ["rule-firings"],
|
|
159
|
+
portability: "derived",
|
|
160
|
+
note: "Stamps of when each rule last did something; the new sandbox starts its own record.",
|
|
161
|
+
},
|
|
85
162
|
// Written by the AGENT's file tools (the drafts skill), read by the owner's approval inbox — the one entry
|
|
86
|
-
// here whose whole point is that a change arrives from outside the browser that renders it.
|
|
87
|
-
|
|
163
|
+
// here whose whole point is that a change arrives from outside the browser that renders it. `authored`:
|
|
164
|
+
// a draft is text somebody wrote, and "find the reddit draft about X" is an ordinary search.
|
|
165
|
+
{ path: ".intentic/drafts/", invalidates: ["drafts"], portability: "carry", authored: true },
|
|
88
166
|
// ---- declared by the extension that renders them (contributes.files), not here ----
|
|
89
167
|
// The path is the DAEMON's (automations-store writes both), the query keys are the intentic.automations
|
|
90
168
|
// extension's. It declares them in its own manifest and the browser unions the two lists, so uninstalling
|
|
@@ -94,6 +172,26 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
94
172
|
invalidates: [],
|
|
95
173
|
why: "Declared by the intentic.automations extension's contributes.files — `automations` is its query key, not core's.",
|
|
96
174
|
portability: "carry",
|
|
175
|
+
versioned: true,
|
|
176
|
+
},
|
|
177
|
+
/* The run history, keyed by automation id — the LEDGER half of what automations.json used to be, and split
|
|
178
|
+
* out of it for the one reason this table's `versioned` note already gives: a tracked file must be worth
|
|
179
|
+
* reviewing. A scheduled automation records a run every time it fires, so every fire dirtied the manifest
|
|
180
|
+
* the owner reviews, and the run records went into `git log` with it — timestamps and conversation ids
|
|
181
|
+
* committed beside the prompt they belong to, burying an actual edit to the automation's config under
|
|
182
|
+
* machine noise. Config is now the only thing in the tracked file, and a fire touches nothing tracked.
|
|
183
|
+
*
|
|
184
|
+
* It is `carry` for the same reason the workflow ledger is: a run history is about the automation, not about
|
|
185
|
+
* the machine, and an export that dropped it would arrive claiming every automation had never run.
|
|
186
|
+
*
|
|
187
|
+
* Its invalidation is the extension's, exactly like the manifest above — and it has to be DECLARED there
|
|
188
|
+
* rather than inherited, because the row renders its run history from this file now: without its own entry
|
|
189
|
+
* a completed run would stop refreshing the view the moment it stopped living in automations.json. */
|
|
190
|
+
{
|
|
191
|
+
path: ".intentic/automation-runs.json",
|
|
192
|
+
invalidates: [],
|
|
193
|
+
why: "Declared by the intentic.automations extension's contributes.files — `automations` is its query key, not core's.",
|
|
194
|
+
portability: "carry",
|
|
97
195
|
},
|
|
98
196
|
{
|
|
99
197
|
path: ".intentic/approvals/",
|
|
@@ -101,6 +199,58 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
101
199
|
why: "Declared by the intentic.automations extension's contributes.files — `automation-approvals` is its query key, not core's.",
|
|
102
200
|
portability: "carry",
|
|
103
201
|
},
|
|
202
|
+
{
|
|
203
|
+
path: ".intentic/automations.seeded.json",
|
|
204
|
+
invalidates: [],
|
|
205
|
+
why: "Which default automations this workspace has been offered (default-automations.ts); nothing renders it — it exists so deleting a seeded automation is final.",
|
|
206
|
+
portability: "carry",
|
|
207
|
+
versioned: true,
|
|
208
|
+
},
|
|
209
|
+
/* The maintenance ledger and probe evidence, written by the daemon's chores-store and rendered by the
|
|
210
|
+
* intentic.maintenance extension — the automations shape exactly: the path is the daemon's, the query keys
|
|
211
|
+
* (`maintenance-report`, `maintenance-runs`) are the extension's own contributes.files. Point-in-time
|
|
212
|
+
* evidence about this workspace, so `carry` like the run ledgers: an export that dropped it would arrive
|
|
213
|
+
* claiming no chore had ever been checked. */
|
|
214
|
+
{
|
|
215
|
+
path: ".intentic/chores/",
|
|
216
|
+
invalidates: [],
|
|
217
|
+
why: "Declared by the intentic.maintenance extension's contributes.files — `maintenance-report`/`maintenance-runs` are its query keys, not core's.",
|
|
218
|
+
portability: "carry",
|
|
219
|
+
},
|
|
220
|
+
/* The documentation STAGING tree (documentation extension's paths.ts): generation writes here, the owner
|
|
221
|
+
* reads and approves here, publishing copies into the repo. `authored` is the whole nature of the entry —
|
|
222
|
+
* these are draft READMEs, drafts-shaped in every way that matters, and "find the staged page about X" is
|
|
223
|
+
* as ordinary a search as finding a post draft. */
|
|
224
|
+
{
|
|
225
|
+
path: ".intentic/docs/",
|
|
226
|
+
invalidates: [],
|
|
227
|
+
why: "Declared by the intentic.documentation extension's contributes.files — `documentation`/`documentation-runs` are its query keys, not core's.",
|
|
228
|
+
portability: "carry",
|
|
229
|
+
authored: true,
|
|
230
|
+
outsideWriter: "the intentic.documentation extension's staging writes (its paths.ts)",
|
|
231
|
+
},
|
|
232
|
+
/* The workflow designs and their run ledger became CORE keys the day runs got cards on the fleet board and
|
|
233
|
+
* a mode of the chat panel (web's useWorkflowRuns): those surfaces exist whether or not the workflows
|
|
234
|
+
* extension is enabled, so their freshness cannot ride an extension's contributes.files — an owner turning
|
|
235
|
+
* the extension off would have frozen the board's run cards mid-run. This push is the ONLY live feed the
|
|
236
|
+
* run surfaces have: the scheduler writes the ledger several times per step and nothing polls for it.
|
|
237
|
+
* The runs file invalidates `workflows` too, because GET /workflows embeds each design's runs
|
|
238
|
+
* (WorkflowSummary) — a settled step changes that answer as surely as an edited design does. */
|
|
239
|
+
{ path: ".intentic/workflows.json", invalidates: ["workflows"], portability: "carry", versioned: true },
|
|
240
|
+
{ path: ".intentic/workflow-runs.json", invalidates: ["workflows", "workflow-runs"], portability: "carry" },
|
|
241
|
+
/* The SAVED loops, which are a manifest and so the opposite of the ledger below them: a handful of entries
|
|
242
|
+
* a person authors, read by two surfaces at once — the workflows page that owns them, and every chat
|
|
243
|
+
* composer's loop picker. Those two are in different windows as often as not (a popped-out chat is its own
|
|
244
|
+
* window), so an edit made on the page has to reach a picker nobody is going to think to reopen. A CORE key
|
|
245
|
+
* rather than the workflows extension's, for the reason the workflow designs beside it are: the composer
|
|
246
|
+
* lists saved loops whether or not that extension is switched on. */
|
|
247
|
+
{ path: ".intentic/loop-designs.json", invalidates: ["loop-designs"], portability: "carry", versioned: true },
|
|
248
|
+
{
|
|
249
|
+
path: ".intentic/loops.json",
|
|
250
|
+
invalidates: [],
|
|
251
|
+
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).",
|
|
252
|
+
portability: "carry",
|
|
253
|
+
},
|
|
104
254
|
|
|
105
255
|
/* ---- reached by no query, for reasons that are not oversights ----
|
|
106
256
|
*
|
|
@@ -139,6 +289,29 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
139
289
|
path: ".intentic/extension-enablement.json",
|
|
140
290
|
invalidates: ["extensions"],
|
|
141
291
|
portability: "carry",
|
|
292
|
+
versioned: true,
|
|
293
|
+
},
|
|
294
|
+
/* Workspace extensions: one directory per extension, consumed straight from the workspace — no clone, no
|
|
295
|
+
* install moment. Written like drafts, by the agent's own file tools (which is the point: an agent authors
|
|
296
|
+
* an extension and it is live for the daemon and every session at once, since .intentic is shared), so this
|
|
297
|
+
* push is what makes one appearing or changing show up on the Extensions tab while the owner watches.
|
|
298
|
+
* `authored` for the same reason as drafts: this is source the agent wrote and will be asked to find —
|
|
299
|
+
* unlike `.intentic/extensions/` below, which is CLONES of source that lives elsewhere. */
|
|
300
|
+
{ path: ".intentic/workspace-extensions/", invalidates: ["extensions"], portability: "carry", authored: true },
|
|
301
|
+
/* What the registry comparison found per installed extension (update available / advisory / post-update
|
|
302
|
+
* health), written by the periodic check and by the update/revert transactions — pushed to the tab because
|
|
303
|
+
* an advisory that auto-disabled something must not wait for a reload to be seen. */
|
|
304
|
+
{ path: ".intentic/extension-updates.json", invalidates: ["extensions"], portability: "carry" },
|
|
305
|
+
/* The owner's per-extension update posture (notify / agent / auto, and the advisory opt-out). Carried:
|
|
306
|
+
* it is a decision about the extension, not about this machine. */
|
|
307
|
+
{ path: ".intentic/extension-update-policy.json", invalidates: ["extensions"], portability: "carry", versioned: true },
|
|
308
|
+
/* Carried, because the evidence is about the extension rather than about the machine: an export that dropped
|
|
309
|
+
* it would arrive claiming every permission was unused, which is worse than arriving with no figures at all. */
|
|
310
|
+
{
|
|
311
|
+
path: ".intentic/extension-usage.json",
|
|
312
|
+
invalidates: [],
|
|
313
|
+
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.",
|
|
314
|
+
portability: "carry",
|
|
142
315
|
},
|
|
143
316
|
{
|
|
144
317
|
path: ".intentic/members.json",
|
|
@@ -149,52 +322,107 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
149
322
|
},
|
|
150
323
|
|
|
151
324
|
// ---- daemon-owned, nothing derives from watching them ----
|
|
325
|
+
/* Keep credentials and conversation state in disjoint top-level trees. Provider homes are intentionally
|
|
326
|
+
* classified as a single secret unit: several CLIs mix OAuth, config, and provider-native thread metadata,
|
|
327
|
+
* and no generic export can safely distinguish those files. The broad root also makes a newly-added provider
|
|
328
|
+
* secret by construction instead of relying on another hand-maintained provider-name list. */
|
|
329
|
+
{
|
|
330
|
+
path: ".intentic/auth/",
|
|
331
|
+
invalidates: [],
|
|
332
|
+
why: "AI-provider credentials and runtime homes; each account is rendered through owner-gated provider routes.",
|
|
333
|
+
portability: "secret",
|
|
334
|
+
note: "Sign the agent's AI accounts in again on the Agent tab.",
|
|
335
|
+
},
|
|
152
336
|
/* Agent session transcripts, rewritten on every streamed token.
|
|
153
337
|
*
|
|
154
338
|
* The memory notes under it (`projects/<slug>/memory/**`) ARE user-facing and the /memory view polls them
|
|
155
339
|
* every 30s, which is the one place in this table where a poll survives a real change feed being available.
|
|
156
340
|
* It stays a poll deliberately: the watcher's exclusion is a DESCENT filter, so reaching those notes means
|
|
157
|
-
* letting it walk `.intentic/claude` → `projects` → every project slug. Measured on the live
|
|
158
|
-
* is +119 watched directories against ~593 today (a fifth more), with 314 continuously-
|
|
159
|
-
* inside the newly-watched set, to make ONE memory directory live. Notes change at
|
|
160
|
-
* poll costs a request a minute and the alternative costs a permanent 20% on the
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
* root. The subtree under `projects/` is the half a bundle exists to carry — the agent's memory notes and
|
|
165
|
-
* every conversation's transcript — while its siblings hold the OAuth that must not leave the sandbox. */
|
|
166
|
-
{
|
|
167
|
-
path: ".intentic/claude/",
|
|
341
|
+
* letting it walk `.intentic/sessions/claude` → `projects` → every project slug. Measured on the live
|
|
342
|
+
* workspace that is +119 watched directories against ~593 today (a fifth more), with 314 continuously-
|
|
343
|
+
* rewritten transcripts inside the newly-watched set, to make ONE memory directory live. Notes change at
|
|
344
|
+
* agent-turn cadence, so the poll costs a request a minute and the alternative costs a permanent 20% on the
|
|
345
|
+
* watcher. */
|
|
346
|
+
{
|
|
347
|
+
path: ".intentic/sessions/claude/",
|
|
168
348
|
invalidates: [],
|
|
169
349
|
why: "Agent session transcripts — see the note above on why the memory notes under it stay polled.",
|
|
170
|
-
portability: "
|
|
171
|
-
note: "Sign the agent's AI accounts in again on the Agent tab.",
|
|
350
|
+
portability: "carry",
|
|
172
351
|
},
|
|
173
352
|
{
|
|
174
|
-
path: ".intentic/
|
|
353
|
+
path: ".intentic/artifacts/",
|
|
175
354
|
invalidates: [],
|
|
176
|
-
why: "
|
|
355
|
+
why: "Durable outputs owned by conversations and extension runs: attachments, browser captures, generated images, acceptance reports, workflow step reports, voice transcripts, and loop ledgers.",
|
|
177
356
|
portability: "carry",
|
|
178
357
|
},
|
|
179
358
|
{
|
|
180
|
-
path: ".intentic/
|
|
359
|
+
path: ".intentic/cache/",
|
|
181
360
|
invalidates: [],
|
|
182
|
-
why: "
|
|
183
|
-
portability: "
|
|
184
|
-
|
|
361
|
+
why: "Rebuildable indexes and caches — the iq index and its vector sidecar, the whisper model; ignored by the watcher and recreated from carried workspace content.",
|
|
362
|
+
portability: "derived",
|
|
363
|
+
},
|
|
364
|
+
/* Connector and extension scratch, one directory per extension under runtime/extensions/<id>
|
|
365
|
+
* (extensionRuntimeDir below — the ONLY way an extension names a home here, so a new one lands under its
|
|
366
|
+
* own id by construction instead of minting a file at the .intentic root). Resume watermarks, cached
|
|
367
|
+
* hour-tokens, gateway discovery state: all of it either expires or re-establishes itself, and classifying
|
|
368
|
+
* the root once is what keeps a token an extension caches tomorrow out of bundles without a second edit. */
|
|
369
|
+
{
|
|
370
|
+
path: ".intentic/runtime/",
|
|
371
|
+
invalidates: [],
|
|
372
|
+
why: "Extension runtime scratch (watermarks, cached short-lived tokens); nothing renders it and gateways re-derive it.",
|
|
373
|
+
portability: "derived",
|
|
374
|
+
outsideWriter: "extensions, through extensionRuntimeDir below",
|
|
185
375
|
},
|
|
186
376
|
{
|
|
187
|
-
path: ".intentic/
|
|
377
|
+
path: ".intentic/tmp/",
|
|
188
378
|
invalidates: [],
|
|
189
|
-
why: "
|
|
379
|
+
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.",
|
|
380
|
+
portability: "derived",
|
|
381
|
+
},
|
|
382
|
+
/* Not written by the daemon at all: pnpm auto-creates its content-addressable store at the project's
|
|
383
|
+
* mountpoint, and `.intentic` is its own mount in an isolated turn — so an install run from under it mints
|
|
384
|
+
* this. Declared anyway, because the table's job is to say what everything under `.intentic` IS: hardlink
|
|
385
|
+
* sources a fresh install rebuilds, which an export must not ship (it reached 1.3 GB on the workspace this
|
|
386
|
+
* entry was written against). */
|
|
387
|
+
{
|
|
388
|
+
path: ".intentic/.pnpm-store/",
|
|
389
|
+
invalidates: [],
|
|
390
|
+
why: "pnpm's content-addressable store, auto-created by installs run from under .intentic; the next install rebuilds it.",
|
|
391
|
+
portability: "derived",
|
|
392
|
+
outsideWriter: "pnpm itself, when an install runs from under .intentic",
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
path: ".intentic/newest-run.json",
|
|
396
|
+
invalidates: [],
|
|
397
|
+
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.",
|
|
398
|
+
portability: "derived",
|
|
399
|
+
note: "The target stamps its own daemon version on first boot.",
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
path: ".intentic/verify.json",
|
|
403
|
+
invalidates: [],
|
|
404
|
+
why: "The dependency verifier's verdict memory; nothing renders it directly — outcomes reach the owner as activity entries and workspace events.",
|
|
190
405
|
portability: "carry",
|
|
191
406
|
},
|
|
192
407
|
{
|
|
193
|
-
path: ".intentic/
|
|
408
|
+
path: ".intentic/verify/",
|
|
194
409
|
invalidates: [],
|
|
195
|
-
why: "
|
|
410
|
+
why: "A running check's wrapper artifacts (log + exit status), read once by the daemon when the panel finishes.",
|
|
411
|
+
portability: "derived",
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
path: ".intentic/ci.json",
|
|
415
|
+
invalidates: [],
|
|
416
|
+
why: "Webhook secret + conclusion memory; the Pipelines view reads it through /ci/runs, not off disk.",
|
|
417
|
+
portability: "secret",
|
|
418
|
+
note: "Re-add the CI webhook on the Pipelines view — its secret is per-sandbox.",
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
path: ".intentic/control-tokens.json",
|
|
422
|
+
invalidates: [],
|
|
423
|
+
why: "Hashed control tokens (the ACP editor bridge, and anything else driving this sandbox from outside), listed on demand by the owner.",
|
|
196
424
|
portability: "identity",
|
|
197
|
-
note: "Mint fresh
|
|
425
|
+
note: "Mint fresh control tokens — the old ones authenticate against the source sandbox.",
|
|
198
426
|
},
|
|
199
427
|
{
|
|
200
428
|
path: ".intentic/owner.json",
|
|
@@ -208,7 +436,13 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
208
436
|
why: "The workspace identity, read from the /events hello frame rather than as a file.",
|
|
209
437
|
portability: "identity",
|
|
210
438
|
},
|
|
211
|
-
{
|
|
439
|
+
{
|
|
440
|
+
path: ".intentic/templates.json",
|
|
441
|
+
invalidates: [],
|
|
442
|
+
why: "Scaffold templates, read when the scaffold dialog opens.",
|
|
443
|
+
portability: "carry",
|
|
444
|
+
versioned: true,
|
|
445
|
+
},
|
|
212
446
|
/* Classed `derived` for size rather than for safety, and it is the one entry where that costs the owner
|
|
213
447
|
* something real: the profiles ARE logged-in sessions. They are also gigabytes of a store Chromium rewrites
|
|
214
448
|
* constantly and versions against its own build, so carrying them ships bulk that the target's Chromium may
|
|
@@ -228,7 +462,156 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = [
|
|
|
228
462
|
note: "Extensions re-clone from the capability manifest on the target's next reconcile.",
|
|
229
463
|
},
|
|
230
464
|
{ path: ".intentic/plugins/", invalidates: [], why: "Agent plugin dirs, read by the SDK's loader each turn.", portability: "carry" },
|
|
231
|
-
|
|
465
|
+
/* THE SKILLS THE OWNER WROTE THEMSELVES, one directory per skill — the source of truth the reconciler copies
|
|
466
|
+
* into `.agents/skills` for the ones currently switched on (settings.json's `skills` list). It is here rather
|
|
467
|
+
* than in the loaded folder for the reason the plugin dirs are: that tree holds only what is currently ON,
|
|
468
|
+
* and a skill switched off has to keep its text somewhere the loaders will not read it from.
|
|
469
|
+
*
|
|
470
|
+
* `versioned`, like the rest of the config slice: a skill changes how the agent behaves, so it earns a diff
|
|
471
|
+
* in the Changes review and a line in `git log` the same way a rule or a persona does. `carry` for the same
|
|
472
|
+
* reason — it is text the owner wrote, with no credential in it and nothing about this machine. */
|
|
473
|
+
{ path: ".intentic/skills/", invalidates: ["skills"], portability: "carry", versioned: true },
|
|
474
|
+
/* ONE FOLDER PER PERSONA — what a session wearing that card is told, and the skills and tools only it gets.
|
|
475
|
+
* Laid out as a Claude Code plugin (`.claude-plugin/plugin.json`, `skills/`, `agents/`, `commands/`,
|
|
476
|
+
* `hooks/`, `.mcp.json`) so the runtime's own loader reads it and this daemon parses none of it, exactly as
|
|
477
|
+
* the plugin checkouts above are read (personas/persona-kit.ts).
|
|
478
|
+
*
|
|
479
|
+
* A SECOND ENTRY BESIDE `personas.json` RATHER THAN A FIELD INSIDE IT, because the two are different kinds
|
|
480
|
+
* of thing to review. The card is a name, some ids and some switches — a few lines that diff cleanly. This
|
|
481
|
+
* is prose and files: a system prompt, a skill, a subagent. Folding a 20k prompt into the JSON would make
|
|
482
|
+
* every persona edit an unreadable diff and put text somebody wrote inside a record nobody writes by hand.
|
|
483
|
+
*
|
|
484
|
+
* `versioned` and `carry` for the same reasons the card and the skills above are: it changes how the agent
|
|
485
|
+
* behaves, it holds no credential, and it belongs in a pull request — which is also what makes it
|
|
486
|
+
* searchable, since every versioned entry already is. */
|
|
487
|
+
{ path: ".intentic/personas/", invalidates: ["personas"], portability: "carry", versioned: true },
|
|
488
|
+
] as const satisfies readonly WorkspaceStateFile[];
|
|
489
|
+
|
|
490
|
+
export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = STATE_FILES;
|
|
491
|
+
|
|
492
|
+
/* The entries the root repo tracks, workspace-root-relative and in declaration order — what history.ts turns
|
|
493
|
+
* into the negations that carve them back out of the wholesale `.intentic` exclusion.
|
|
494
|
+
*
|
|
495
|
+
* Derived rather than written down beside the exclude rule, for the reason this whole file exists: the git rule
|
|
496
|
+
* lives in the daemon and the classification lives here, and a second hand-kept copy of "which config is
|
|
497
|
+
* reviewable" is a copy that goes stale the first time someone adds a store. Marking an entry `versioned` is now
|
|
498
|
+
* the entire change — the exclude list follows on the next boot, in both places it is written. */
|
|
499
|
+
export const VERSIONED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned).map((file) => file.path);
|
|
500
|
+
|
|
501
|
+
/* The `.intentic` slice a workspace SEARCH may surface: configuration a person reviews (`versioned`) plus the
|
|
502
|
+
* authored-content dirs (`authored`) — drafts, staged docs, workspace extensions. Everything else under
|
|
503
|
+
* `.intentic` is machine state, and the search engine (iq's floor) denies it BY DEFAULT off this list, the
|
|
504
|
+
* same default-deny the portability classes are built on and for the same reason: a deny list is a list a new
|
|
505
|
+
* ledger is forgotten from, and the forgetting is silent — it ranked loop iteration history and cloned
|
|
506
|
+
* third-party extension source against the user's own code for months before this derivation existed.
|
|
507
|
+
*
|
|
508
|
+
* Note what falls out without a special case: `capabilities.json` is `secret` and unversioned, so the index
|
|
509
|
+
* stops copying capability tokens into search text — the exact boundary the floor already drew for `auth/`. */
|
|
510
|
+
export const SEARCHABLE_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned || file.authored).map(
|
|
511
|
+
(file) => file.path,
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
/* THE ONE WAY AN EXTENSION NAMES ITS SCRATCH HOME — `.intentic/runtime/extensions/<id>`, workspace-relative
|
|
515
|
+
* and forward-slash so the browser bundle can hold it too; callers join it onto whatever root is in force.
|
|
516
|
+
*
|
|
517
|
+
* It exists for the reason statePath does one table over: before it, every gateway spelled the layout itself
|
|
518
|
+
* and one extension (deployments) simply didn't, minting `komodo.json` at the `.intentic` root where nothing
|
|
519
|
+
* classified it. An extension that composes through this helper cannot land outside its own directory, so the
|
|
520
|
+
* runtime/ entry's `derived` covers whatever it writes tomorrow. Extension ids are validated slugs already;
|
|
521
|
+
* the replace is defence in depth against a path ever being built from something else. */
|
|
522
|
+
export const extensionRuntimeDir = (extension: string): string => `${STATE_DIR}/runtime/extensions/${extension.replaceAll(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
523
|
+
|
|
524
|
+
/* The manifests whose problems the unreadable-manifest notice SHOWS — the handful a person hand-edits — and the
|
|
525
|
+
* one fact that decides it is already in the table above.
|
|
526
|
+
*
|
|
527
|
+
* Every store reads through the same `jsonFile`, so every store reports what it could not make sense of, and for
|
|
528
|
+
* a long time the notice showed all of them. That is wrong twice over. Its advice — fix the file and this clears
|
|
529
|
+
* on its own — is addressed to somebody holding an editor, which is true of `settings.json` and false of a
|
|
530
|
+
* daemon-written LEDGER nobody opens: a run history that stopped matching a schema the build tightened is not a
|
|
531
|
+
* mistake the owner made, and the card asked them to repair sixty kilobytes of machine JSON by hand. Worse, a
|
|
532
|
+
* file that reports into the notice without feeding the notice's QUERY leaves a complaint no write can refresh,
|
|
533
|
+
* so it sits on screen until the daemon restarts — which is exactly how the workflow ledger's entry became
|
|
534
|
+
* permanent furniture.
|
|
535
|
+
*
|
|
536
|
+
* Both follow from one rule, which is why this derives rather than lists: a file's problems are shown IFF a write
|
|
537
|
+
* to that file refreshes the notice. Declaring `manifests` in `invalidates` is the entire opt-in, so the edit
|
|
538
|
+
* that puts a file on the card is the same edit that keeps it current, and neither can be done without the
|
|
539
|
+
* other. A ledger that breaks still falls back and still sets its unreadable bytes aside on the next write
|
|
540
|
+
* (store/json-file.ts) — it just stops asking the owner to fix it. */
|
|
541
|
+
export const REPORTED_MANIFEST_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.invalidates.includes("manifests")).map(
|
|
542
|
+
(file) => file.path,
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
// Accepts either separator, like isLockedWorkspacePath below: the daemon holds these as platform paths and makes
|
|
546
|
+
// them relative at the last moment, and normalizing at each call site is the one that eventually gets forgotten.
|
|
547
|
+
export const isReportedManifest = (relPath: string): boolean => REPORTED_MANIFEST_PATHS.includes(relPath.replaceAll("\\", "/"));
|
|
548
|
+
|
|
549
|
+
/* Old directory names are never read or migrated. Keep that finite set in one quarantine record so access,
|
|
550
|
+
* export, and search cannot reinterpret abandoned machine state as ordinary workspace content after a rename.
|
|
551
|
+
* `artifacts` still carry; the distinction here tells portability only which retired roots are secrets or
|
|
552
|
+
* derived — and tells the state janitor which it may DELETE: a retired `derived` root is a rebuildable cache
|
|
553
|
+
* by its own classification, so leaving 466 MB of abandoned model where only a manual `rm` reaches it was
|
|
554
|
+
* quarantine doing half its job. Secret and artifact roots stay until an owner removes them by hand: deleting
|
|
555
|
+
* content is not the janitor's call, only deleting what the class already says is disposable. */
|
|
556
|
+
export const RETIRED_WORKSPACE_STATE_DIRS = {
|
|
557
|
+
secret: ["claude", "codex", "kimi", "opencode", "cliproxy"],
|
|
558
|
+
derived: ["iq", "extensions-runtime", "whisper", "browser/output"],
|
|
559
|
+
artifacts: ["attachments", "acceptance", "loops", "workflow-runs", "transcripts"],
|
|
560
|
+
} as const;
|
|
561
|
+
|
|
562
|
+
/* THE DAEMON'S OWN CONTROL PLANE — the entries directly under the workspace root's `.intentic/` that the file
|
|
563
|
+
* API refuses to read, write, move or delete for anyone, the owner included (workspace/workspace-files.ts holds
|
|
564
|
+
* the enforcement and the full reasoning for each name).
|
|
565
|
+
*
|
|
566
|
+
* The list lives HERE, in the package both sides import, because the browser has to draw the same rule the
|
|
567
|
+
* daemon enforces. It didn't, and the gap was a small piece of theatre: the explorer listed `capabilities.json`
|
|
568
|
+
* like any other file, opening it flashed a tab, the read came back with nothing there, and the tab closed
|
|
569
|
+
* itself — a refusal acted out as a glitch. A file the app will not open should say so before it is clicked,
|
|
570
|
+
* which takes a rule the explorer can consult, not a status code it can only react to.
|
|
571
|
+
*
|
|
572
|
+
* Naming these to the browser gives nothing away that the tree did not already publish — it listed them, sizes
|
|
573
|
+
* and all. What stays behind the guard is the only thing that ever mattered: the bytes. */
|
|
574
|
+
const LOCKED_STATE_ENTRIES: ReadonlySet<string> = new Set([
|
|
575
|
+
"owner.json",
|
|
576
|
+
"members.json",
|
|
577
|
+
"capabilities.json",
|
|
578
|
+
"ci.json",
|
|
579
|
+
"claude.json",
|
|
580
|
+
"auth",
|
|
581
|
+
"sessions",
|
|
582
|
+
"browser",
|
|
583
|
+
...RETIRED_WORKSPACE_STATE_DIRS.secret,
|
|
584
|
+
]);
|
|
585
|
+
|
|
586
|
+
/* Whether a workspace-root-relative path lands in that control plane — and so is shown locked rather than
|
|
587
|
+
* opened. Scoped deliberately tight, matching the guard: only the ROOT `.intentic` counts (a repo's own nested
|
|
588
|
+
* one is ordinary content) and only these entries within it, subtrees included, so a new provider dropped under
|
|
589
|
+
* `auth/` is covered without a second edit.
|
|
590
|
+
*
|
|
591
|
+
* The ROOT's own `.git` joins them. It is the pointer to the shadow history repo kept off the workspace so the
|
|
592
|
+
* agent cannot rewrite its own past; a NESTED repo's `.git` is ordinary content and stays browsable.
|
|
593
|
+
*
|
|
594
|
+
* Accepts either slash so a caller holding a platform path doesn't have to normalize first. */
|
|
595
|
+
export const isLockedWorkspacePath = (relPath: string): boolean => {
|
|
596
|
+
const segments = relPath.split(/[\\/]/).filter((segment) => segment !== "" && segment !== ".");
|
|
597
|
+
if (segments[0] === ".git") {
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
return segments.length >= 2 && segments[0] === STATE_DIR && LOCKED_STATE_ENTRIES.has(segments[1] ?? "");
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
/* Every path this table declares, as a type. `as const` above is what makes it one, and it is what finally makes
|
|
604
|
+
* the first sentence of this file's header TRUE rather than aspirational.
|
|
605
|
+
*
|
|
606
|
+
* "The daemon builds its store paths from `path`" was the design; the code did not. `composition.ts` and twenty
|
|
607
|
+
* files beside it spelled the same layout a SECOND way — `join(root, ".intentic", "settings.json")` — with
|
|
608
|
+
* nothing tying the two spellings together. Rename a store's file and this table keeps declaring the old name:
|
|
609
|
+
* no error, no failing test, just a view that quietly stops refreshing, which is the exact failure the table was
|
|
610
|
+
* written to end and the exact way drafts went missing.
|
|
611
|
+
*
|
|
612
|
+
* So the daemon joins through `statePath` (workspace/state-paths.ts), which takes one of THESE and nothing else.
|
|
613
|
+
* A rename is now a compile error at every site that names the file, in both packages, or it is not a rename. */
|
|
614
|
+
export type WorkspaceStatePath = (typeof STATE_FILES)[number]["path"];
|
|
232
615
|
|
|
233
616
|
/* The query keys a batch of changed paths makes stale, deduped and stable. The browser's `/events` handler calls
|
|
234
617
|
* this; keeping it here rather than in the web means the rule is unit-testable without a query client, and the
|
|
@@ -249,3 +632,12 @@ export const staleQueryKeys = (paths: readonly string[], contributed: readonly F
|
|
|
249
632
|
.flatMap((file) => file.invalidates),
|
|
250
633
|
),
|
|
251
634
|
];
|
|
635
|
+
|
|
636
|
+
/* Every query key any watched file feeds — what a NEW /events connection invalidates wholesale (core's table
|
|
637
|
+
* plus the running extensions'). The file push is these keys' ONLY live feed, and a `workspaceChanged` frame
|
|
638
|
+
* produced while the stream was down is a frame nobody will ever resend — so each key's view would sit stale
|
|
639
|
+
* until the file's NEXT write, indefinitely for anything that settled while the browser was away. Re-asking on
|
|
640
|
+
* connect bounds the damage at one cheap read per key, which is what lets those views go entirely unpolled. */
|
|
641
|
+
export const fileBoundQueryKeys = (contributed: readonly FileContribution[]): readonly string[] => [
|
|
642
|
+
...new Set([...WORKSPACE_STATE_FILES, ...contributed].flatMap((file) => file.invalidates)),
|
|
643
|
+
];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex.contract.d.ts","sourceRoot":"","sources":["../../src/contracts/codex.contract.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;IAEtB,MAAM;;;;;;;;;;;;;CACT,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex.contract.js","sourceRoot":"","sources":["../../src/contracts/codex.contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAK7C,MAAM,CAAC,MAAM,aAAa,GAAG;IAEzB,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;CAClF,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare const geminiContract: {
|
|
2
|
-
models: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
|
|
3
|
-
models: import("zod").ZodArray<import("zod").ZodObject<{
|
|
4
|
-
id: import("zod").ZodString;
|
|
5
|
-
label: import("zod").ZodString;
|
|
6
|
-
efforts: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
7
|
-
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
-
badges: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodEnum<{
|
|
9
|
-
fast: "fast";
|
|
10
|
-
reasoning: "reasoning";
|
|
11
|
-
}>>>;
|
|
12
|
-
}, import("zod/v4/core").$strip>>;
|
|
13
|
-
default: import("zod").ZodString;
|
|
14
|
-
}, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=gemini.contract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.contract.d.ts","sourceRoot":"","sources":["../../src/contracts/gemini.contract.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc;IAEvB,MAAM;;;;;;;;;;;;;CACT,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.contract.js","sourceRoot":"","sources":["../../src/contracts/gemini.contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAM7C,MAAM,CAAC,MAAM,cAAc,GAAG;IAE1B,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;CACnF,CAAC"}
|