@intentic/sandbox-contract 1.240.0 → 1.242.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 +52 -16
- package/dist/agent-catalog.d.ts +5 -28
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +21 -157
- package/dist/agent-catalog.js.map +1 -1
- package/dist/agent-run-model.d.ts +3 -2
- package/dist/agent-run-model.d.ts.map +1 -1
- package/dist/agent-run-model.js +9 -6
- package/dist/agent-run-model.js.map +1 -1
- package/dist/agent-runtimes.d.ts +27 -0
- package/dist/agent-runtimes.d.ts.map +1 -0
- package/dist/agent-runtimes.js +113 -0
- package/dist/agent-runtimes.js.map +1 -0
- package/dist/approvals-execution.d.ts +11 -0
- package/dist/approvals-execution.d.ts.map +1 -0
- package/dist/approvals-execution.js +44 -0
- package/dist/approvals-execution.js.map +1 -0
- package/dist/arrival.d.ts +151 -0
- package/dist/arrival.d.ts.map +1 -0
- package/dist/arrival.js +56 -0
- package/dist/arrival.js.map +1 -0
- package/dist/card-status.d.ts +5 -0
- package/dist/card-status.d.ts.map +1 -0
- package/dist/card-status.js +74 -0
- package/dist/card-status.js.map +1 -0
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js +1 -1
- package/dist/chores/chores.js.map +1 -1
- package/dist/command-classes.d.ts +0 -1
- package/dist/command-classes.d.ts.map +1 -1
- package/dist/command-classes.js +9 -2
- package/dist/command-classes.js.map +1 -1
- package/dist/command-run.d.ts +10 -0
- package/dist/command-run.d.ts.map +1 -0
- package/dist/command-run.js +46 -0
- package/dist/command-run.js.map +1 -0
- package/dist/contracts/agent.contract.d.ts +991 -771
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.d.ts +345 -337
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +20 -2
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/approvals.contract.d.ts +99 -0
- package/dist/contracts/approvals.contract.d.ts.map +1 -0
- package/dist/contracts/approvals.contract.js +32 -0
- package/dist/contracts/approvals.contract.js.map +1 -0
- package/dist/contracts/ci.contract.d.ts +1 -4
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.js +1 -9
- package/dist/contracts/ci.contract.js.map +1 -1
- package/dist/contracts/claude.contract.d.ts +9 -0
- package/dist/contracts/claude.contract.d.ts.map +1 -1
- package/dist/contracts/cursor.contract.d.ts +6 -0
- package/dist/contracts/cursor.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.d.ts +63 -1
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +22 -4
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/grok.contract.d.ts +3 -0
- package/dist/contracts/grok.contract.d.ts.map +1 -1
- package/dist/contracts/keys.contract.d.ts +81 -0
- package/dist/contracts/keys.contract.d.ts.map +1 -0
- package/dist/contracts/keys.contract.js +51 -0
- package/dist/contracts/keys.contract.js.map +1 -0
- package/dist/contracts/panels.contract.d.ts +7 -0
- package/dist/contracts/panels.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.js +2 -2
- package/dist/contracts/providers.contract.d.ts +2 -0
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.d.ts +84 -86
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/safety.contract.d.ts +35 -0
- package/dist/contracts/safety.contract.d.ts.map +1 -0
- package/dist/contracts/safety.contract.js +32 -0
- package/dist/contracts/safety.contract.js.map +1 -0
- package/dist/contracts/sessions.contract.d.ts +73 -337
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.d.ts +30 -32
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.d.ts +139 -337
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/translator.contract.d.ts +31 -3
- package/dist/contracts/translator.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.d.ts +29 -20
- package/dist/contracts/usage.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.js +13 -0
- package/dist/contracts/usage.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts +8 -0
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/conversation-ids.d.ts +2 -0
- package/dist/conversation-ids.d.ts.map +1 -1
- package/dist/conversation-ids.js +8 -0
- package/dist/conversation-ids.js.map +1 -1
- package/dist/credential-material.d.ts +1 -0
- package/dist/credential-material.d.ts.map +1 -1
- package/dist/credential-material.js +24 -2
- package/dist/credential-material.js.map +1 -1
- package/dist/definition.d.ts +51 -93
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +6 -28
- package/dist/definition.js.map +1 -1
- package/dist/events.d.ts +1831 -2285
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +155 -55
- package/dist/events.js.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +1 -0
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +1959 -1903
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/ingress-protocol.d.ts +13 -1
- package/dist/ingress-protocol.d.ts.map +1 -1
- package/dist/ingress-protocol.js +19 -0
- package/dist/ingress-protocol.js.map +1 -1
- package/dist/mentions.d.ts +3 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +13 -0
- package/dist/mentions.js.map +1 -0
- package/dist/needs-action.d.ts +7 -0
- package/dist/needs-action.d.ts.map +1 -0
- package/dist/needs-action.js +3 -0
- package/dist/needs-action.js.map +1 -0
- package/dist/overlay-lint.d.ts +7 -0
- package/dist/overlay-lint.d.ts.map +1 -0
- package/dist/overlay-lint.js +68 -0
- package/dist/overlay-lint.js.map +1 -0
- package/dist/owner-ticket.d.ts +18 -0
- package/dist/owner-ticket.d.ts.map +1 -0
- package/dist/owner-ticket.js +51 -0
- package/dist/owner-ticket.js.map +1 -0
- package/dist/plan-pools.d.ts +12 -0
- package/dist/plan-pools.d.ts.map +1 -0
- package/dist/plan-pools.js +30 -0
- package/dist/plan-pools.js.map +1 -0
- package/dist/provider-specs.d.ts +228 -0
- package/dist/provider-specs.d.ts.map +1 -0
- package/dist/provider-specs.js +124 -0
- package/dist/provider-specs.js.map +1 -0
- package/dist/quick-model.d.ts.map +1 -1
- package/dist/quick-model.js +2 -1
- package/dist/quick-model.js.map +1 -1
- package/dist/runner-protocol.js +2 -2
- package/dist/runner-protocol.js.map +1 -1
- package/dist/runtime-state.d.ts +2 -2
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +1 -1
- package/dist/runtime-state.js.map +1 -1
- package/dist/safety-policy.d.ts +49 -0
- package/dist/safety-policy.d.ts.map +1 -0
- package/dist/safety-policy.js +52 -0
- package/dist/safety-policy.js.map +1 -0
- package/dist/schemas/agent.d.ts +21 -3
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +18 -8
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +19 -0
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +15 -0
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/approvals.d.ts +241 -0
- package/dist/schemas/approvals.d.ts.map +1 -0
- package/dist/schemas/approvals.js +63 -0
- package/dist/schemas/approvals.js.map +1 -0
- package/dist/schemas/automations.d.ts +5 -0
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/ci.d.ts +5 -9
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +3 -10
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/computers.d.ts +31 -5
- package/dist/schemas/computers.d.ts.map +1 -1
- package/dist/schemas/computers.js +7 -5
- package/dist/schemas/computers.js.map +1 -1
- package/dist/schemas/environment.d.ts +11 -131
- package/dist/schemas/environment.d.ts.map +1 -1
- package/dist/schemas/environment.js +5 -42
- package/dist/schemas/environment.js.map +1 -1
- package/dist/schemas/git-history.d.ts +4 -0
- package/dist/schemas/git-history.d.ts.map +1 -1
- package/dist/schemas/git.d.ts +179 -0
- package/dist/schemas/git.d.ts.map +1 -1
- package/dist/schemas/git.js +39 -1
- package/dist/schemas/git.js.map +1 -1
- package/dist/schemas/panels.d.ts +21 -0
- package/dist/schemas/panels.d.ts.map +1 -1
- package/dist/schemas/panels.js +5 -0
- package/dist/schemas/panels.js.map +1 -1
- package/dist/schemas/plan-limits.d.ts +50 -3
- package/dist/schemas/plan-limits.d.ts.map +1 -1
- package/dist/schemas/plan-limits.js +11 -6
- package/dist/schemas/plan-limits.js.map +1 -1
- package/dist/schemas/provider-oauth.d.ts +6 -0
- package/dist/schemas/provider-oauth.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.d.ts +2 -1
- package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.js +2 -1
- package/dist/schemas/provider-subscriptions.js.map +1 -1
- package/dist/schemas/settings.d.ts +29 -16
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +13 -20
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/system.d.ts +3 -0
- package/dist/schemas/system.d.ts.map +1 -1
- package/dist/schemas/system.js +5 -1
- package/dist/schemas/system.js.map +1 -1
- package/dist/schemas/workspace-repos.d.ts +14 -0
- package/dist/schemas/workspace-repos.d.ts.map +1 -1
- package/dist/schemas/workspace-repos.js +5 -0
- package/dist/schemas/workspace-repos.js.map +1 -1
- package/dist/schemas/workspace-tree.d.ts +1 -0
- package/dist/schemas/workspace-tree.d.ts.map +1 -1
- package/dist/schemas/workspace-tree.js +3 -0
- package/dist/schemas/workspace-tree.js.map +1 -1
- package/dist/transcript-fold.d.ts +31 -0
- package/dist/transcript-fold.d.ts.map +1 -0
- package/dist/transcript-fold.js +457 -0
- package/dist/transcript-fold.js.map +1 -0
- package/dist/workspace-state.d.ts +20 -3
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +22 -2
- package/dist/workspace-state.js.map +1 -1
- package/package.json +27 -5
- package/src/agent-catalog.test.ts +1 -1
- package/src/agent-catalog.ts +76 -555
- package/src/agent-run-model.test.ts +31 -15
- package/src/agent-run-model.ts +26 -12
- package/src/agent-runtimes.ts +419 -0
- package/src/approvals-execution.ts +96 -0
- package/src/arrival.ts +160 -0
- package/src/capability-ledger.test.ts +6 -4
- package/src/card-status.ts +93 -0
- package/src/chores/chores.ts +6 -3
- package/src/command-classes.test.ts +25 -0
- package/src/command-classes.ts +47 -5
- package/src/command-run.ts +78 -0
- package/src/contract-lock.test.ts +1 -1
- package/src/contract-lock.ts +2 -2
- package/src/contracts/agents.contract.ts +35 -2
- package/src/contracts/approvals.contract.ts +37 -0
- package/src/contracts/ci.contract.ts +0 -13
- package/src/contracts/git.contract.ts +28 -3
- package/src/contracts/keys.contract.ts +79 -0
- package/src/contracts/prepush.contract.ts +3 -3
- package/src/contracts/safety.contract.ts +48 -0
- package/src/contracts/usage.contract.ts +22 -0
- package/src/conversation-ids.test.ts +31 -1
- package/src/conversation-ids.ts +37 -3
- package/src/credential-material.test.ts +69 -1
- package/src/credential-material.ts +86 -5
- package/src/definition.ts +25 -53
- package/src/events.ts +374 -173
- package/src/history-state.ts +6 -0
- package/src/index.ts +24 -5
- package/src/ingress-protocol.ts +52 -1
- package/src/mentions.test.ts +22 -0
- package/src/mentions.ts +25 -0
- package/src/needs-action.ts +14 -0
- package/src/overlay-lint.test.ts +89 -0
- package/src/overlay-lint.ts +116 -0
- package/src/owner-ticket.test.ts +54 -0
- package/src/owner-ticket.ts +102 -0
- package/src/plan-pools.test.ts +71 -0
- package/src/plan-pools.ts +82 -0
- package/src/provider-specs.test.ts +130 -0
- package/src/provider-specs.ts +352 -0
- package/src/quick-model.ts +9 -5
- package/src/runner-protocol.ts +2 -2
- package/src/runtime-state.ts +6 -6
- package/src/safety-policy.ts +165 -0
- package/src/schemas/agent.ts +62 -17
- package/src/schemas/agents.ts +71 -0
- package/src/schemas/approvals.ts +174 -0
- package/src/schemas/ci.ts +19 -26
- package/src/schemas/computers.ts +52 -11
- package/src/schemas/environment.ts +21 -100
- package/src/schemas/git.ts +121 -6
- package/src/schemas/issues.ts +1 -1
- package/src/schemas/panels.ts +20 -0
- package/src/schemas/plan-limits.ts +58 -11
- package/src/schemas/provider-subscriptions.ts +7 -2
- package/src/schemas/settings.ts +67 -93
- package/src/schemas/system.ts +12 -1
- package/src/schemas/workspace-repos.ts +9 -0
- package/src/schemas/workspace-tree.ts +11 -0
- package/src/transcript-fold.test.ts +493 -0
- package/src/transcript-fold.ts +655 -0
- package/src/workspace-state.test.ts +77 -29
- package/src/workspace-state.ts +99 -31
- package/dist/contracts/drafts.contract.d.ts +0 -57
- package/dist/contracts/drafts.contract.d.ts.map +0 -1
- package/dist/contracts/drafts.contract.js +0 -32
- package/dist/contracts/drafts.contract.js.map +0 -1
- package/dist/definition-action.d.ts +0 -7
- package/dist/definition-action.d.ts.map +0 -1
- package/dist/definition-action.js +0 -3
- package/dist/definition-action.js.map +0 -1
- package/dist/publish-drafts.d.ts +0 -7
- package/dist/publish-drafts.d.ts.map +0 -1
- package/dist/publish-drafts.js +0 -20
- package/dist/publish-drafts.js.map +0 -1
- package/dist/schemas/drafts.d.ts +0 -84
- package/dist/schemas/drafts.d.ts.map +0 -1
- package/dist/schemas/drafts.js +0 -44
- package/dist/schemas/drafts.js.map +0 -1
- package/src/contracts/drafts.contract.ts +0 -35
- package/src/definition-action.ts +0 -8
- package/src/publish-drafts.ts +0 -59
- package/src/schemas/drafts.ts +0 -108
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
isReviewableLockedPath,
|
|
9
9
|
REPORTED_MANIFEST_PATHS,
|
|
10
10
|
SEARCHABLE_STATE_PATHS,
|
|
11
|
+
SHARED_STATE_PATHS,
|
|
11
12
|
STATE_GROUP_DIR,
|
|
12
13
|
type StateGroup,
|
|
13
14
|
stateGroupOf,
|
|
@@ -47,14 +48,14 @@ describe(`staleQueryKeys`, () => {
|
|
|
47
48
|
it(`matches a name family and a one-file-per-entry directory through one prefix each`, () => {
|
|
48
49
|
// environment.Dockerfile, environment.custom.Dockerfile, environment.approved.Dockerfile: one entry.
|
|
49
50
|
expect(staleQueryKeys([`.intentic/config/environment.custom.Dockerfile`], [])).toEqual([`environment`]);
|
|
50
|
-
expect(staleQueryKeys([`.intentic/config/
|
|
51
|
+
expect(staleQueryKeys([`.intentic/config/approvals/post-1.json`], [])).toEqual([`approvals`]);
|
|
51
52
|
});
|
|
52
53
|
|
|
53
|
-
it(`refreshes the
|
|
54
|
-
// The regression this table was reorganized around: the
|
|
54
|
+
it(`refreshes the Approvals view when the AGENT writes a proposal`, () => {
|
|
55
|
+
// The regression this table was reorganized around: the approvals skill writes these files directly, so
|
|
55
56
|
// there is no browser mutation to hang an invalidate on: the watcher push is the only signal, and it
|
|
56
57
|
// used to be dropped on the floor.
|
|
57
|
-
expect(staleQueryKeys([`.intentic/config/
|
|
58
|
+
expect(staleQueryKeys([`.intentic/config/approvals/post-1.json`], [])).toEqual([`approvals`]);
|
|
58
59
|
});
|
|
59
60
|
|
|
60
61
|
it(`ignores unrelated churn under .intentic/`, () => {
|
|
@@ -158,7 +159,7 @@ describe(`WORKSPACE_STATE_FILES`, () => {
|
|
|
158
159
|
it(`states a reason for every entry that invalidates nothing`, () => {
|
|
159
160
|
// An empty `invalidates` is a real answer (daemon machine state, a deliberately-polled surface, a path
|
|
160
161
|
// whose query keys belong to an extension), but a SILENT one is indistinguishable from the omission this
|
|
161
|
-
// table exists to prevent, which is exactly how
|
|
162
|
+
// table exists to prevent, which is exactly how approvals went missing. Requiring the reason is what makes
|
|
162
163
|
// the difference visible at review time.
|
|
163
164
|
for (const file of WORKSPACE_STATE_FILES) {
|
|
164
165
|
if (file.invalidates.length === 0) {
|
|
@@ -172,10 +173,12 @@ describe(`WORKSPACE_STATE_FILES`, () => {
|
|
|
172
173
|
});
|
|
173
174
|
|
|
174
175
|
it(`keeps directory entries slash-terminated so they cannot swallow a sibling`, () => {
|
|
175
|
-
// `.intentic/config/
|
|
176
|
+
// `.intentic/config/approvals` without the slash would also prefix-match a future `.intentic/approvals-archive.json`.
|
|
176
177
|
for (const file of WORKSPACE_STATE_FILES.filter((entry) => entry.invalidates.length > 0)) {
|
|
177
178
|
const isFamilyPrefix = file.path.endsWith(`.`);
|
|
178
|
-
|
|
179
|
+
// `.md` is the safety policy: the one state file whose reader is a model rather than a parser, so
|
|
180
|
+
// it is prose on disk rather than JSON.
|
|
181
|
+
const isFile = file.path.endsWith(`.json`) || file.path.endsWith(`.Dockerfile`) || file.path.endsWith(`.md`);
|
|
179
182
|
expect(isFile || isFamilyPrefix || file.path.endsWith(`/`), file.path).toBe(true);
|
|
180
183
|
}
|
|
181
184
|
});
|
|
@@ -224,7 +227,7 @@ describe(`isLockedWorkspacePath`, () => {
|
|
|
224
227
|
// The dir itself is browsable, and most of what is in it is a file a person may legitimately read.
|
|
225
228
|
expect(isLockedWorkspacePath(`.intentic`)).toBe(false);
|
|
226
229
|
expect(isLockedWorkspacePath(`.intentic/config/settings.json`)).toBe(false);
|
|
227
|
-
expect(isLockedWorkspacePath(`.intentic/config/
|
|
230
|
+
expect(isLockedWorkspacePath(`.intentic/config/approvals/post-1.json`)).toBe(false);
|
|
228
231
|
});
|
|
229
232
|
|
|
230
233
|
it(`locks the ROOT's own .git and nobody else's`, () => {
|
|
@@ -320,52 +323,59 @@ describe(`VERSIONED_STATE_PATHS`, () => {
|
|
|
320
323
|
* consequence of editing the table above: the review the flag itself exists to force. */
|
|
321
324
|
it(`tracks exactly the configuration slice plus the agent's own authored output`, () => {
|
|
322
325
|
expect(VERSIONED_STATE_PATHS.toSorted()).toEqual([
|
|
323
|
-
|
|
326
|
+
`${STATE_DIR}/config/approvals/`,
|
|
327
|
+
`${STATE_DIR}/config/automations.json`,
|
|
328
|
+
// Which apps the daemon starts at boot: the starter site on a fresh box, and whatever the owner adds.
|
|
329
|
+
`${STATE_DIR}/config/autostart.json`,
|
|
324
330
|
/* The connections themselves, and the entry that took the longest to earn its place: it was classed
|
|
325
331
|
* `secret` on the strength of holding each capability's credential, which stopped being true when the
|
|
326
332
|
* vault took the values out and left the shape behind. Connecting a deployment orchestrator, or
|
|
327
333
|
* granting a connected computer shell and screen control, is the largest change made to what this
|
|
328
334
|
* sandbox can DO, and it used to leave no diff. */
|
|
329
|
-
|
|
330
|
-
|
|
335
|
+
`${STATE_DIR}/config/capabilities.json`,
|
|
336
|
+
`${STATE_DIR}/config/capability-dismissals.json`,
|
|
331
337
|
/* The two entries the AGENT authors on its own initiative, and the reason `versioned` is not read as
|
|
332
338
|
* config-only. Both are the sandbox acting outward: a draft publishes words under the owner's name,
|
|
333
339
|
* a workspace extension is code that runs in the app and can serve HTTP with the workspace under
|
|
334
340
|
* node:fs, and both used to reach that far with no diff anywhere. Kept rather than consumed, one
|
|
335
341
|
* small file at a time, so tracking them yields a record instead of churn. */
|
|
336
|
-
`.intentic/config/drafts/`,
|
|
337
342
|
/* Where each agent engine takes its version from. Tracked for the same reason heavy-commands is:
|
|
338
343
|
* it is a standing decision about what runs for everyone on this workspace — tracking upstream's
|
|
339
344
|
* newest Claude Code, or pinning one while a regression is open — and `git log` is the only thing
|
|
340
345
|
* that answers "since when". */
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
+
`${STATE_DIR}/config/engines.json`,
|
|
347
|
+
`${STATE_DIR}/config/environment.Dockerfile`,
|
|
348
|
+
`${STATE_DIR}/config/environment.custom.Dockerfile`,
|
|
349
|
+
`${STATE_DIR}/config/environment.d/`,
|
|
350
|
+
`${STATE_DIR}/config/extension-enablement.json`,
|
|
346
351
|
/* Its twin, and the pair is the argument: the SWITCH was already tracked while the configuration
|
|
347
352
|
* behind it was not, so a commit could record turning an extension on and say nothing about what it
|
|
348
353
|
* was told to do. Tracked once its declared-secret values moved to the vault. */
|
|
349
|
-
|
|
354
|
+
`${STATE_DIR}/config/extension-settings.json`,
|
|
350
355
|
// The owner's per-extension update posture (notify / agent / auto): a standing decision about
|
|
351
356
|
// what may run unattended, which is exactly the kind of edit worth a line in `git log`.
|
|
352
|
-
|
|
357
|
+
`${STATE_DIR}/config/extension-update-policy.json`,
|
|
353
358
|
// Which commands are heavy enough to take turns, and how many may run at once. Tracked because
|
|
354
359
|
// raising that limit is a decision about every session sharing the box, and `git log` is the only
|
|
355
360
|
// thing that answers "since when have we been allowing four of these at a time".
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
361
|
+
`${STATE_DIR}/config/heavy-commands.json`,
|
|
362
|
+
`${STATE_DIR}/config/loop-designs.json`,
|
|
363
|
+
`${STATE_DIR}/config/personas.json`,
|
|
359
364
|
// A persona's own kit: the prompt it runs on and the skills only its turns reach. Tracked for the
|
|
360
365
|
// reason its card is, one step further: this is the text that decides how that persona behaves.
|
|
361
|
-
|
|
362
|
-
|
|
366
|
+
`${STATE_DIR}/config/personas/`,
|
|
367
|
+
/* The safety policy: prose deciding when an agent stops to ask before running something. Tracked for
|
|
368
|
+
* the reason settings.json is, and more sharply — it is the standing answer to "how much may this
|
|
369
|
+
* thing do unasked", the agent may edit it on the owner's instruction, and `git log` is the only
|
|
370
|
+
* thing that answers "since when did we stop being asked about force-pushes". */
|
|
371
|
+
`${STATE_DIR}/config/safety.md`,
|
|
372
|
+
`${STATE_DIR}/config/settings.json`,
|
|
363
373
|
// The skills the owner wrote. Tracked for the reason the rules in settings.json are: text that
|
|
364
374
|
// changes how the agent behaves is worth a diff and a line in `git log`.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
375
|
+
`${STATE_DIR}/config/skills/`,
|
|
376
|
+
`${STATE_DIR}/config/templates.json`,
|
|
377
|
+
`${STATE_DIR}/config/workflows.json`,
|
|
378
|
+
`${STATE_DIR}/config/workspace-extensions/`,
|
|
369
379
|
]);
|
|
370
380
|
});
|
|
371
381
|
|
|
@@ -439,7 +449,7 @@ describe(`state groups`, () => {
|
|
|
439
449
|
|
|
440
450
|
it(`sorts the entries a browsing owner would recognise`, () => {
|
|
441
451
|
expect(stateGroupPaths(`config`)).toContain(`.intentic/config/personas/`);
|
|
442
|
-
expect(stateGroupPaths(`config`)).toContain(`.intentic/config/
|
|
452
|
+
expect(stateGroupPaths(`config`)).toContain(`.intentic/config/approvals/`);
|
|
443
453
|
expect(stateGroupPaths(`records`)).toContain(`.intentic/records/sessions/claude/`);
|
|
444
454
|
expect(stateGroupPaths(`records`)).toContain(`.intentic/records/artifacts/`);
|
|
445
455
|
expect(stateGroupPaths(`local`)).toContain(`.intentic/local/cache/`);
|
|
@@ -491,6 +501,44 @@ describe(`state groups`, () => {
|
|
|
491
501
|
});
|
|
492
502
|
});
|
|
493
503
|
|
|
504
|
+
/* THE MOUNT BOUNDARY, and the claim that lets isolation bind by group instead of over the whole state dir: the
|
|
505
|
+
* shared prefixes and the tracked entries never overlap. A tracked entry under a shared prefix would be the old
|
|
506
|
+
* bug back in one folder, git in a worktree writing through a bind onto the live tree, and an untracked entry
|
|
507
|
+
* under no shared prefix is a transcript or a staged doc written into a per-worktree copy nobody reads. */
|
|
508
|
+
describe(`SHARED_STATE_PATHS`, () => {
|
|
509
|
+
const under = (path: string, prefix: string): boolean => path === prefix || path.startsWith(prefix);
|
|
510
|
+
|
|
511
|
+
it(`is the four untracked groups whole, plus the one untracked entry inside config`, () => {
|
|
512
|
+
expect(SHARED_STATE_PATHS.toSorted()).toEqual([
|
|
513
|
+
`.intentic/config/docs/`,
|
|
514
|
+
`.intentic/identity/`,
|
|
515
|
+
`.intentic/local/`,
|
|
516
|
+
`.intentic/records/`,
|
|
517
|
+
`.intentic/secrets/`,
|
|
518
|
+
]);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
it(`never covers a tracked entry`, () => {
|
|
522
|
+
for (const path of VERSIONED_STATE_PATHS) {
|
|
523
|
+
expect([path, SHARED_STATE_PATHS.some((shared) => under(path, shared))]).toEqual([path, false]);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it(`covers every untracked entry`, () => {
|
|
528
|
+
for (const file of WORKSPACE_STATE_FILES) {
|
|
529
|
+
if (file.versioned !== true) {
|
|
530
|
+
expect([file.path, SHARED_STATE_PATHS.some((shared) => under(file.path, shared))]).toEqual([file.path, true]);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it(`spells every prefix as a directory, so a bind can never prefix-match a sibling`, () => {
|
|
536
|
+
for (const path of SHARED_STATE_PATHS) {
|
|
537
|
+
expect(path.endsWith(`/`), path).toBe(true);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
|
|
494
542
|
/* WHAT THE OWNER'S MACHINE KEEPS. The sync ignored the whole state dir, so losing a sandbox lost every persona,
|
|
495
543
|
* skill, automation, draft and transcript in it: a backup that held only the source tree. These pin the two
|
|
496
544
|
* halves of the fix: the slice that now comes down, and the credentials that still must not. */
|
package/src/workspace-state.ts
CHANGED
|
@@ -10,11 +10,11 @@ import type { StateFile } from "./state-portability.js";
|
|
|
10
10
|
* maintained separately from the paths the daemon actually writes (composition.ts), two lists of the same
|
|
11
11
|
* fact, in two packages, with nothing tying them together.
|
|
12
12
|
*
|
|
13
|
-
* They drifted, exactly as that shape always does.
|
|
14
|
-
* skill puts a file there) and rendered by the
|
|
15
|
-
* a
|
|
16
|
-
* Extension settings and the members list were missing for the same reason; writing them out is what
|
|
17
|
-
* that neither is
|
|
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
18
|
*
|
|
19
19
|
* So the binding is declared HERE, once, in the package both the daemon and the browser already import, and
|
|
20
20
|
* each side derives what it needs: the daemon builds its store paths from `path`, the browser builds its
|
|
@@ -38,7 +38,7 @@ import type { StateFile } from "./state-portability.js";
|
|
|
38
38
|
* `path` is workspace-root-relative, forward-slash, the space `workspaceChanged` paths arrive in. Matching is
|
|
39
39
|
* by PREFIX, which lets one entry cover three shapes without a second matching rule:
|
|
40
40
|
* - an exact file `.intentic/config/settings.json`
|
|
41
|
-
* - a directory `.intentic/config/
|
|
41
|
+
* - a directory `.intentic/config/approvals/` (one file per approval)
|
|
42
42
|
* - a name family `.intentic/config/environment.custom.` (…Dockerfile and anything later named beside it)
|
|
43
43
|
* A directory entry keeps its trailing slash so it can never prefix-match a sibling file. Entries may NEST,
|
|
44
44
|
* see stateFileFor, which resolves the longest match rather than the first. */
|
|
@@ -221,6 +221,46 @@ const STATE_FILES = [
|
|
|
221
221
|
},
|
|
222
222
|
|
|
223
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
|
+
},
|
|
224
264
|
/* Which agent commands are heavy enough to take turns, and how many may run at once (the daemon reads it
|
|
225
265
|
* per Bash command: platform/heavy-commands.ts).
|
|
226
266
|
*
|
|
@@ -261,22 +301,24 @@ const STATE_FILES = [
|
|
|
261
301
|
* that page but reads its own route, and a channel change must not cost every open Environment tab a
|
|
262
302
|
* re-read of the overlay it did not touch. */
|
|
263
303
|
{ path: ".intentic/config/engines.json", invalidates: ["engines"], portability: "carry", versioned: true },
|
|
264
|
-
/* Written by the AGENT's file tools (the
|
|
304
|
+
/* Written by the AGENT's file tools (the approvals skill), read by the owner's approval inbox, the one entry
|
|
265
305
|
* here whose whole point is that a change arrives from outside the browser that renders it. `authored`:
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
|
|
306
|
+
* an approval is text somebody wrote, a post or a description of an action, and "find the reddit post
|
|
307
|
+
* about X" is an ordinary search.
|
|
308
|
+
*
|
|
309
|
+
* `versioned` because an approval is the furthest-reaching thing the agent writes: a post goes out under the
|
|
310
|
+
* owner's name, to an audience, and cannot be recalled; an action spends or sends or deletes. The inbox
|
|
311
|
+
* already gates that, but a gate is not a record. Declining one used to erase it, so the question "what has
|
|
312
|
+
* this agent tried to do" had no answer at all, and an approved item's own history (what was proposed, what
|
|
313
|
+
* the owner changed, when it actually happened) lived only in a file nobody could diff.
|
|
314
|
+
*
|
|
315
|
+
* It costs almost nothing to track, which is why the ledger objection does not reach it: an approval is one
|
|
316
|
+
* small file, written a handful of times across its whole life (proposed → approved → done, with
|
|
317
|
+
* `finishedAt`/`result` stamped at the end), and it is KEPT afterwards rather than consumed, so tracking
|
|
318
|
+
* yields a durable record instead of the add/delete churn a queue would produce. Nothing in one is a
|
|
319
|
+
* credential: a platform, a target, the words, a description of what will be done, all of it meant to be
|
|
320
|
+
* read by the owner anyway. */
|
|
321
|
+
{ path: ".intentic/config/approvals/", invalidates: ["approvals"], portability: "carry", versioned: true, authored: true },
|
|
280
322
|
// ---- declared by the extension that renders them (contributes.files), not here ----
|
|
281
323
|
// The path is the DAEMON's (automations-store writes both), the query keys are the intentic.automations
|
|
282
324
|
// extension's. It declares them in its own manifest and the browser unions the two lists, so uninstalling
|
|
@@ -310,7 +352,7 @@ const STATE_FILES = [
|
|
|
310
352
|
{
|
|
311
353
|
path: ".intentic/records/approvals/",
|
|
312
354
|
invalidates: [],
|
|
313
|
-
why: "Declared by the intentic.
|
|
355
|
+
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.",
|
|
314
356
|
portability: "carry",
|
|
315
357
|
},
|
|
316
358
|
/* The bug-report inbox, one file per fingerprint, written by the daemon's issues-store as reports arrive
|
|
@@ -321,8 +363,8 @@ const STATE_FILES = [
|
|
|
321
363
|
* exported and restored elsewhere that arrived claiming nothing had ever crashed would have thrown away
|
|
322
364
|
* the one record that says which bug is worth fixing first, and the counts are the whole of that record.
|
|
323
365
|
*
|
|
324
|
-
* NOT `versioned`, and the
|
|
325
|
-
*
|
|
366
|
+
* NOT `versioned`, and the approvals entry is the contrast worth reading: an approval is authored, reviewable
|
|
367
|
+
* and acts under the owner's name, so it earns a diff. An issue is machine-recorded telemetry whose count
|
|
326
368
|
* moves on every crash: tracking it would put a commit's worth of churn in `git log` per bad afternoon,
|
|
327
369
|
* and nothing in it is a decision anybody made. */
|
|
328
370
|
{
|
|
@@ -344,7 +386,7 @@ const STATE_FILES = [
|
|
|
344
386
|
},
|
|
345
387
|
/* The documentation STAGING tree (documentation extension's paths.ts): generation writes here, the owner
|
|
346
388
|
* reads and approves here, publishing copies into the repo. `authored` is the whole nature of the entry,
|
|
347
|
-
* these are draft READMEs,
|
|
389
|
+
* these are draft READMEs, approvals-shaped in every way that matters, and "find the staged page about X" is
|
|
348
390
|
* as ordinary a search as finding a post draft. */
|
|
349
391
|
{
|
|
350
392
|
path: ".intentic/config/docs/",
|
|
@@ -440,10 +482,10 @@ const STATE_FILES = [
|
|
|
440
482
|
versioned: true,
|
|
441
483
|
},
|
|
442
484
|
/* Workspace extensions: one directory per extension, consumed straight from the workspace, no clone, no
|
|
443
|
-
* install moment. Written like
|
|
485
|
+
* install moment. Written like approvals, by the agent's own file tools (which is the point: an agent authors
|
|
444
486
|
* an extension and it is live for the daemon and every session at once, since .intentic is shared), so this
|
|
445
487
|
* push is what makes one appearing or changing show up on the Extensions tab while the owner watches.
|
|
446
|
-
* `authored` for the same reason as
|
|
488
|
+
* `authored` for the same reason as approvals: this is source the agent wrote and will be asked to find,
|
|
447
489
|
* unlike `.intentic/extensions/` below, which is CLONES of source that lives elsewhere.
|
|
448
490
|
*
|
|
449
491
|
* `versioned` FOR THAT SAME REASON, which is the whole argument. Every other load path an extension can take
|
|
@@ -682,7 +724,7 @@ export const WORKSPACE_STATE_FILES: readonly WorkspaceStateFile[] = STATE_FILES;
|
|
|
682
724
|
export const VERSIONED_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.filter((file) => file.versioned).map((file) => file.path);
|
|
683
725
|
|
|
684
726
|
/* The `.intentic` slice a workspace SEARCH may surface: configuration a person reviews (`versioned`) plus the
|
|
685
|
-
* authored-content dirs (`authored`),
|
|
727
|
+
* authored-content dirs (`authored`), approvals, staged docs, workspace extensions. Everything else under
|
|
686
728
|
* `.intentic` is machine state, and the search engine (iq's floor) denies it BY DEFAULT off this list, the
|
|
687
729
|
* same default-deny the portability classes are built on and for the same reason: a deny list is a list a new
|
|
688
730
|
* ledger is forgotten from, and the forgetting is silent, it ranked loop iteration history and cloned
|
|
@@ -714,8 +756,8 @@ export const SEARCHABLE_STATE_PATHS: readonly string[] = WORKSPACE_STATE_FILES.f
|
|
|
714
756
|
* the same three questions it always did; the group, the folder it belongs in, and every rule that reads them
|
|
715
757
|
* follow with no further edit. */
|
|
716
758
|
export type StateGroup =
|
|
717
|
-
/* Reviewed and reviewable: settings, personas, skills,
|
|
718
|
-
* by the root repo, searchable, backed up, and carried into a new sandbox. Two of its members (
|
|
759
|
+
/* Reviewed and reviewable: settings, personas, skills, approvals, staged docs, the environment overlay. Tracked
|
|
760
|
+
* by the root repo, searchable, backed up, and carried into a new sandbox. Two of its members (approvals, staged
|
|
719
761
|
* docs) are authored content rather than configuration, and the folder is still called `config`, the word
|
|
720
762
|
* that makes seventeen of the nineteen instantly clear beats one that makes all nineteen vague. */
|
|
721
763
|
| "config"
|
|
@@ -784,6 +826,32 @@ export const stateGroupOf = (file: WorkspaceStateFile): StateGroup => {
|
|
|
784
826
|
export const stateGroupPaths = (group: StateGroup): readonly string[] =>
|
|
785
827
|
WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group).map((file) => file.path);
|
|
786
828
|
|
|
829
|
+
/* WHAT AN ISOLATED TURN SHARES LIVE WITH THE MAIN TREE, and what is its own. The state dir is split along ONE
|
|
830
|
+
* line, and it is the line git already draws: what the root repo TRACKS (`versioned`) is the worktree's own
|
|
831
|
+
* checkout, edited on the agent's branch, reviewed in its diff and landed like code; everything git does NOT
|
|
832
|
+
* track is bound in from the main tree (agents/isolation.ts), one directory for every conversation, because a
|
|
833
|
+
* transcript, a ledger, a browser capture or a staged doc written into a per-worktree copy is simply lost.
|
|
834
|
+
*
|
|
835
|
+
* The two used to be one bind over the whole dir, with the tracked slice sparse-excluded from every worktree to
|
|
836
|
+
* keep git from writing through it. That put the ONE thing a person reviews outside the one door that records
|
|
837
|
+
* provenance: an agent's settings edit, approval, environment fragment or skill went straight into the owner's
|
|
838
|
+
* working tree, unattributed, with no branch commit and nothing for a land to conflict on. Binding by group
|
|
839
|
+
* ends both problems at once, nothing tracked sits behind a bind, so nothing git does in a worktree can reach
|
|
840
|
+
* the live tree, and the sparse machinery has nothing left to guard.
|
|
841
|
+
*
|
|
842
|
+
* WHOLE GROUP DIRS WHERE THE WHOLE GROUP IS UNTRACKED (records, local, identity, secrets), not their entries: a
|
|
843
|
+
* file an extension writes under `records/` without declaring it must still land in the shared tree, and a
|
|
844
|
+
* per-entry bind would strand it in the worktree. Only a group that MIXES tracked and untracked entries (config,
|
|
845
|
+
* for the staged docs tree) is bound entry by entry. Derived, so a store added tomorrow is placed by its
|
|
846
|
+
* `versioned` flag alone, and the layout guard in workspace-state.test.ts pins that no tracked entry can ever
|
|
847
|
+
* sit under a shared prefix. Trailing slash kept on every entry, as the table spells directories. */
|
|
848
|
+
export const SHARED_STATE_PATHS: readonly string[] = STATE_GROUPS.flatMap((group) => {
|
|
849
|
+
const files = WORKSPACE_STATE_FILES.filter((file) => stateGroupOf(file) === group);
|
|
850
|
+
return files.some((file) => file.versioned === true)
|
|
851
|
+
? files.filter((file) => file.versioned !== true).map((file) => file.path)
|
|
852
|
+
: [`${STATE_GROUP_DIR[group]}/`];
|
|
853
|
+
});
|
|
854
|
+
|
|
787
855
|
/* THE SLICE DESKTOP-SYNC COPIES DOWN, ordinary state and the records that bind this sandbox to its owner,
|
|
788
856
|
* minus anything that opted out (see `backup` on the interface).
|
|
789
857
|
*
|
|
@@ -927,7 +995,7 @@ export const isReviewableLockedPath = (relPath: string): boolean => {
|
|
|
927
995
|
* files beside it spelled the same layout a SECOND way, `join(root, ".intentic", "settings.json")`, with
|
|
928
996
|
* nothing tying the two spellings together. Rename a store's file and this table keeps declaring the old name:
|
|
929
997
|
* no error, no failing test, just a view that quietly stops refreshing, which is the exact failure the table was
|
|
930
|
-
* written to end and the exact way
|
|
998
|
+
* written to end and the exact way approvals went missing.
|
|
931
999
|
*
|
|
932
1000
|
* So the daemon joins through `statePath` (workspace/state-paths.ts), which takes one of THESE and nothing else.
|
|
933
1001
|
* A rename is now a compile error at every site that names the file, in both packages, or it is not a rename. */
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
export declare const draftsContract: {
|
|
2
|
-
list: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, import("zod").ZodObject<{
|
|
3
|
-
drafts: import("zod").ZodArray<import("zod").ZodObject<{
|
|
4
|
-
platform: import("zod").ZodString;
|
|
5
|
-
actsAs: import("zod").ZodOptional<import("zod").ZodString>;
|
|
6
|
-
content: import("zod").ZodString;
|
|
7
|
-
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
8
|
-
target: import("zod").ZodOptional<import("zod").ZodString>;
|
|
9
|
-
media: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
10
|
-
scheduledAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
11
|
-
status: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
12
|
-
approved: "approved";
|
|
13
|
-
failed: "failed";
|
|
14
|
-
posted: "posted";
|
|
15
|
-
posting: "posting";
|
|
16
|
-
proposed: "proposed";
|
|
17
|
-
}>>;
|
|
18
|
-
createdAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
19
|
-
postingAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
20
|
-
postedAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
21
|
-
postedUrl: import("zod").ZodOptional<import("zod").ZodString>;
|
|
22
|
-
error: import("zod").ZodOptional<import("zod").ZodString>;
|
|
23
|
-
id: import("zod").ZodString;
|
|
24
|
-
}, import("zod/v4/core").$strip>>;
|
|
25
|
-
invalid: import("zod").ZodArray<import("zod").ZodString>;
|
|
26
|
-
}, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
|
|
27
|
-
upsert: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<import("zod").ZodObject<{
|
|
28
|
-
platform: import("zod").ZodString;
|
|
29
|
-
actsAs: import("zod").ZodOptional<import("zod").ZodString>;
|
|
30
|
-
content: import("zod").ZodString;
|
|
31
|
-
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
32
|
-
target: import("zod").ZodOptional<import("zod").ZodString>;
|
|
33
|
-
media: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
34
|
-
scheduledAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
35
|
-
status: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
36
|
-
approved: "approved";
|
|
37
|
-
failed: "failed";
|
|
38
|
-
posted: "posted";
|
|
39
|
-
posting: "posting";
|
|
40
|
-
proposed: "proposed";
|
|
41
|
-
}>>;
|
|
42
|
-
createdAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
43
|
-
postingAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
44
|
-
postedAt: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
45
|
-
postedUrl: import("zod").ZodOptional<import("zod").ZodString>;
|
|
46
|
-
error: import("zod").ZodOptional<import("zod").ZodString>;
|
|
47
|
-
id: import("zod").ZodString;
|
|
48
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
49
|
-
ok: import("zod").ZodLiteral<true>;
|
|
50
|
-
}, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
|
|
51
|
-
remove: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<import("zod").ZodObject<{
|
|
52
|
-
id: import("zod").ZodString;
|
|
53
|
-
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
54
|
-
ok: import("zod").ZodLiteral<true>;
|
|
55
|
-
}, import("zod/v4/core").$strip>, Record<never, never>, Record<never, never>>;
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=drafts.contract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drafts.contract.d.ts","sourceRoot":"","sources":["../../src/contracts/drafts.contract.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc;IACvB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;IAQJ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;IASN,MAAM;;;;;CAST,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { oc } from "@orpc/contract";
|
|
2
|
-
import { DraftIdParamSchema, DraftsListSchema, DraftSummarySchema } from "../schemas/drafts.js";
|
|
3
|
-
import { OkSchema } from "../schemas/shared.js";
|
|
4
|
-
export const draftsContract = {
|
|
5
|
-
list: oc
|
|
6
|
-
.route({
|
|
7
|
-
method: "GET",
|
|
8
|
-
path: "/drafts",
|
|
9
|
-
summary: "Posts waiting for your approval",
|
|
10
|
-
description: "The queue of things an agent has written and would like to publish. Nothing here has gone anywhere yet.",
|
|
11
|
-
})
|
|
12
|
-
.output(DraftsListSchema),
|
|
13
|
-
upsert: oc
|
|
14
|
-
.route({
|
|
15
|
-
method: "POST",
|
|
16
|
-
path: "/drafts",
|
|
17
|
-
summary: "Approve, edit or retry a draft",
|
|
18
|
-
description: "All three are the same act with a different field changed, so they share one call. Send the draft back as you want it.",
|
|
19
|
-
})
|
|
20
|
-
.input(DraftSummarySchema)
|
|
21
|
-
.output(OkSchema),
|
|
22
|
-
remove: oc
|
|
23
|
-
.route({
|
|
24
|
-
method: "DELETE",
|
|
25
|
-
path: "/drafts/{id}",
|
|
26
|
-
summary: "Reject a draft",
|
|
27
|
-
description: "Throws one away unposted.",
|
|
28
|
-
})
|
|
29
|
-
.input(DraftIdParamSchema)
|
|
30
|
-
.output(OkSchema),
|
|
31
|
-
};
|
|
32
|
-
//# sourceMappingURL=drafts.contract.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drafts.contract.js","sourceRoot":"","sources":["../../src/contracts/drafts.contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKhD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC1B,IAAI,EAAE,EAAE;SACH,KAAK,CAAC;QACH,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,iCAAiC;QAC1C,WAAW,EAAE,yGAAyG;KACzH,CAAC;SACD,MAAM,CAAC,gBAAgB,CAAC;IAC7B,MAAM,EAAE,EAAE;SACL,KAAK,CAAC;QACH,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,gCAAgC;QACzC,WAAW,EAAE,wHAAwH;KACxI,CAAC;SACD,KAAK,CAAC,kBAAkB,CAAC;SACzB,MAAM,CAAC,QAAQ,CAAC;IACrB,MAAM,EAAE,EAAE;SACL,KAAK,CAAC;QACH,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,2BAA2B;KAC3C,CAAC;SACD,KAAK,CAAC,kBAAkB,CAAC;SACzB,MAAM,CAAC,QAAQ,CAAC;CACxB,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare const DefinitionActionSchema: z.ZodObject<{
|
|
3
|
-
subject: z.ZodString;
|
|
4
|
-
detail: z.ZodString;
|
|
5
|
-
}, z.core.$strip>;
|
|
6
|
-
export type DefinitionAction = z.infer<typeof DefinitionActionSchema>;
|
|
7
|
-
//# sourceMappingURL=definition-action.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-action.d.ts","sourceRoot":"","sources":["../src/definition-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,sBAAsB;;;iBAAwD,CAAC;AAC5F,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-action.js","sourceRoot":"","sources":["../src/definition-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC"}
|
package/dist/publish-drafts.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const APPROVAL_HOLD_MS = 60000;
|
|
2
|
-
export declare const DIRECT_PUBLISH_PLATFORMS: ReadonlySet<string>;
|
|
3
|
-
export declare const publishTurnPrompt: (drafts: readonly {
|
|
4
|
-
readonly id: string;
|
|
5
|
-
readonly platform: string;
|
|
6
|
-
}[]) => string;
|
|
7
|
-
//# sourceMappingURL=publish-drafts.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publish-drafts.d.ts","sourceRoot":"","sources":["../src/publish-drafts.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAYvC,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAwB,CAAC;AASlF,eAAO,MAAM,iBAAiB,WAAY,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,KAAG,MAiB1F,CAAC"}
|
package/dist/publish-drafts.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export const APPROVAL_HOLD_MS = 60_000;
|
|
2
|
-
export const DIRECT_PUBLISH_PLATFORMS = new Set(["discord"]);
|
|
3
|
-
export const publishTurnPrompt = (drafts) => [
|
|
4
|
-
`Publish these approved post drafts, which are due now. They live in .intentic/config/drafts/, one JSON file each:`,
|
|
5
|
-
``,
|
|
6
|
-
...drafts.map((draft) => `- ${draft.id}.json (${draft.platform})`),
|
|
7
|
-
``,
|
|
8
|
-
`Take them ONE AT A TIME, and for each:`,
|
|
9
|
-
`1. Read the file. Set "status":"posting" BEFORE you act, so a turn that dies here cannot double-post.`,
|
|
10
|
-
`2. Post exactly its "content": with its "title", "target" and "media", using that platform's skill.`,
|
|
11
|
-
` A "target" that is a URL means this draft is a REPLY to whatever is at it: open that exact URL and`,
|
|
12
|
-
` reply where it lands. On reddit a comment permalink (.../comments/<post>/<slug>/<comment>/) has to`,
|
|
13
|
-
` nest under that comment rather than becoming a new top-level comment on the thread.`,
|
|
14
|
-
`3. Set "status":"posted" plus "postedAt" (epoch ms) and, when the platform gives you one, "postedUrl".`,
|
|
15
|
-
` If it failed, set "status":"failed" plus an "error" saying what went wrong in plain words the owner`,
|
|
16
|
-
` can act on, then move to the next draft instead of retrying in a loop.`,
|
|
17
|
-
``,
|
|
18
|
-
`Never rewrite the content: the owner approved these exact words. Never touch a draft not listed above.`,
|
|
19
|
-
].join(`\n`);
|
|
20
|
-
//# sourceMappingURL=publish-drafts.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publish-drafts.js","sourceRoot":"","sources":["../src/publish-drafts.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAYvC,MAAM,CAAC,MAAM,wBAAwB,GAAwB,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AASlF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAqE,EAAU,EAAE,CAC/G;IACI,mHAAmH;IACnH,EAAE;IACF,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,EAAE,UAAU,KAAK,CAAC,QAAQ,GAAG,CAAC;IAClE,EAAE;IACF,wCAAwC;IACxC,uGAAuG;IACvG,qGAAqG;IACrG,uGAAuG;IACvG,uGAAuG;IACvG,wFAAwF;IACxF,wGAAwG;IACxG,wGAAwG;IACxG,2EAA2E;IAC3E,EAAE;IACF,wGAAwG;CAC3G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
|