@awebai/oats 0.22.12 → 0.22.16
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/bin/oats.mjs +714 -25
- package/capabilities/oats-okf/bin/oats-okf.mjs +26 -2
- package/capabilities/oats-okf/oats.json +18 -3
- package/docs/capabilities.md +7 -0
- package/docs/capability-manifest.schema.json +32 -0
- package/docs/design/2026-09-07-architecture-reassessment.md +131 -0
- package/docs/design/2026-09-07-desktop-souls-capabilities.md +50 -0
- package/docs/design/operations-contract.md +123 -0
- package/docs/desktop.md +16 -0
- package/docs/execution-targets.md +21 -0
- package/docs/release-notes/v0.22.13.md +44 -0
- package/docs/release-notes/v0.22.14.md +48 -0
- package/docs/release-notes/v0.22.15.md +48 -0
- package/docs/release-notes/v0.22.16.md +53 -0
- package/docs/schedules.md +9 -0
- package/lib/attachments.mjs +164 -0
- package/lib/core.mjs +37 -2
- package/lib/schedule.mjs +32 -8
- package/lib/servers.mjs +35 -2
- package/lib/session-viewer.mjs +4 -0
- package/package-catalog.json +29 -8
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ const jsonFail = (code, message) => { process.stdout.write(JSON.stringify({ sche
|
|
|
44
44
|
// --help/-h never runs a command here either (the kernel answers it from the
|
|
45
45
|
// manifest since 0.22.6; this keeps an older kernel from spawning a harvester).
|
|
46
46
|
if (process.argv.slice(2).some((a) => a === "--help" || a === "-h")) {
|
|
47
|
-
process.stdout.write("oats okf harvest [--json] [--from-record] [--force] promote this instance's pending notes (and record windows) into its soul by spawning a memory-harvest worker; --help never
|
|
47
|
+
process.stdout.write("oats okf harvest [--json] [--from-record] [--force] promote this instance's pending notes (and record windows) into its soul by spawning a memory-harvest worker; --help never runs it\noats okf inspect [--json] answer this instance's working knowledge (STATE.md, log.md, pending notes) as labeled documents\n");
|
|
48
48
|
process.exit(0);
|
|
49
49
|
}
|
|
50
50
|
const event = process.env.OATS_EVENT || process.argv[2];
|
|
@@ -473,6 +473,30 @@ _(the single next action — keep this current; a fresh session on any model res
|
|
|
473
473
|
if (JSON_MODE) jsonFail(e.code || "E_HARVEST_FAILED", `harvest spawn failed (notes are safe on disk): ${e.message || e}`);
|
|
474
474
|
warnFail(`harvest spawn failed (notes are safe on disk): ${e.message || e}`);
|
|
475
475
|
}
|
|
476
|
+
} else if (event === "inspect") {
|
|
477
|
+
// VIEW OPERATION (kernel contract, docs/design/operations-contract.md):
|
|
478
|
+
// the instance's working knowledge as labeled documents, read from the
|
|
479
|
+
// home this command runs in. Text only; paths are provenance for the
|
|
480
|
+
// reader. Answers the JSON-v1 envelope regardless of --json.
|
|
481
|
+
try {
|
|
482
|
+
const CAP = 256 * 1024;
|
|
483
|
+
const doc = (label, file) => {
|
|
484
|
+
if (!existsSync(file)) return null;
|
|
485
|
+
const bytes = readFileSync(file);
|
|
486
|
+
const truncated = bytes.length > CAP;
|
|
487
|
+
let text = truncated ? bytes.subarray(0, CAP).toString("utf8") : bytes.toString("utf8");
|
|
488
|
+
if (truncated && text.endsWith("\uFFFD")) text = text.slice(0, -1);
|
|
489
|
+
return { label, kind: "markdown", path: file, text, ...(truncated ? { truncated: true, bytes: bytes.length } : {}) };
|
|
490
|
+
};
|
|
491
|
+
const documents = [doc("Working state (STATE.md)", join(home, "STATE.md")), doc("Log (log.md)", join(home, "log.md"))].filter(Boolean);
|
|
492
|
+
const notesDir = join(home, "notes");
|
|
493
|
+
const notes = existsSync(notesDir) ? readdirSync(notesDir).filter((f) => f.endsWith(".md")).sort() : [];
|
|
494
|
+
for (const f of notes) { const d = doc(`Pending note: ${f}`, join(notesDir, f)); if (d) documents.push(d); }
|
|
495
|
+
const summary = documents.length ? `${documents.length} document${documents.length === 1 ? "" : "s"}: ${existsSync(join(home, "STATE.md")) ? "state" : "no state"}, ${existsSync(join(home, "log.md")) ? "log" : "no log"}, ${notes.length} pending note${notes.length === 1 ? "" : "s"}` : "no working memory in this home yet (STATE.md, log.md and notes/ are written by the instance)";
|
|
496
|
+
process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: true, result: { summary, documents } }) + "\n"); process.exit(0);
|
|
497
|
+
} catch (e) {
|
|
498
|
+
process.stdout.write(JSON.stringify({ schemaVersion: 1, ok: false, error: { code: "E_INSPECT_FAILED", message: String(e.message || e).slice(0, 300) } }) + "\n"); process.exit(1);
|
|
499
|
+
}
|
|
476
500
|
} else if (event === "retire") {
|
|
477
501
|
// Retirement is intentionally a no-op for knowledge (for now): promotion happens
|
|
478
502
|
// continuously via agent-initiated harvest. Uncommitted notes die with the home —
|
|
@@ -480,5 +504,5 @@ _(the single next action — keep this current; a fresh session on any model res
|
|
|
480
504
|
// before finishing.
|
|
481
505
|
out({ meta: {} });
|
|
482
506
|
} else {
|
|
483
|
-
warn(`unknown event "${event}" (expected soul-scaffold|spawn|retire)`);
|
|
507
|
+
warn(`unknown event "${event}" (expected soul-scaffold|spawn|retire|harvest|inspect)`);
|
|
484
508
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"capability": "oats.okf",
|
|
3
3
|
"command": "okf",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"compatibility": {
|
|
6
6
|
"oats": ">=0.22.3"
|
|
7
7
|
},
|
|
8
8
|
"layer": "knowledge",
|
|
9
|
-
"description": "Knowledge layer via OKF: soul bundles, instance memory (STATE.md/log.md/notes/), continuous post-commit harvest into the soul (commit, PR, or direct-edit for local souls), craft + memory skills, validator.",
|
|
9
|
+
"description": "Knowledge layer via OKF: soul bundles, instance memory (STATE.md/log.md/notes/), continuous post-commit harvest into the soul (commit, PR, or direct-edit for local souls), craft + memory skills, validator; declares the operations a GUI or schedule may run (inspect, harvest).",
|
|
10
10
|
"requires": [],
|
|
11
11
|
"settings": {
|
|
12
12
|
"harvest-runtime": {
|
|
@@ -29,11 +29,26 @@
|
|
|
29
29
|
"skills"
|
|
30
30
|
],
|
|
31
31
|
"commands": {
|
|
32
|
-
"harvest": "bin/oats-okf.mjs harvest"
|
|
32
|
+
"harvest": "bin/oats-okf.mjs harvest",
|
|
33
|
+
"inspect": "bin/oats-okf.mjs inspect"
|
|
33
34
|
},
|
|
34
35
|
"inject": "injects/okf.md",
|
|
35
36
|
"hooks": {
|
|
36
37
|
"soul-scaffold": "bin/oats-okf.mjs soul-scaffold",
|
|
37
38
|
"spawn": "bin/oats-okf.mjs spawn"
|
|
39
|
+
},
|
|
40
|
+
"operations": {
|
|
41
|
+
"inspect": {
|
|
42
|
+
"kind": "view",
|
|
43
|
+
"command": "inspect",
|
|
44
|
+
"context": "home",
|
|
45
|
+
"description": "Show this instance's working knowledge: STATE.md, log.md and pending notes"
|
|
46
|
+
},
|
|
47
|
+
"harvest": {
|
|
48
|
+
"kind": "action",
|
|
49
|
+
"command": "harvest",
|
|
50
|
+
"context": "home",
|
|
51
|
+
"description": "Promote this instance's pending notes (or captured record) into its soul by spawning a memory-harvest worker"
|
|
52
|
+
}
|
|
38
53
|
}
|
|
39
54
|
}
|
package/docs/capabilities.md
CHANGED
|
@@ -503,3 +503,10 @@ The source packages live under `capabilities/`. Acquired packages live under
|
|
|
503
503
|
`<level>/.agents/capabilities/installed/` (gitignored, restorable); packages
|
|
504
504
|
authored at a scope live under `<level>/.agents/capabilities/owned/`
|
|
505
505
|
(committed where the scope is a git repo). Within one scope `owned/` overrides `installed/` on ID collision.
|
|
506
|
+
|
|
507
|
+
## Operations a capability declares
|
|
508
|
+
|
|
509
|
+
A manifest may declare `operations` (named actions or views delegating to
|
|
510
|
+
its own commands) that a GUI or a schedule invokes through `oats operation
|
|
511
|
+
run <layer>:<name>`; `oats inspect --json` reports them with availability.
|
|
512
|
+
See [docs/design/operations-contract.md](design/operations-contract.md).
|
|
@@ -150,6 +150,38 @@
|
|
|
150
150
|
"minLength": 1
|
|
151
151
|
}
|
|
152
152
|
},
|
|
153
|
+
"operations": {
|
|
154
|
+
"description": "Named operations a GUI or scheduler may invoke through `oats operation run`, each delegating to one of this manifest's commands. kind \"view\" answers { documents: [{label, kind, path, text}] }; \"action\" (default) runs something. context \"home\" (default) runs in an instance home, \"scope\" in the config scope.",
|
|
155
|
+
"type": "object",
|
|
156
|
+
"propertyNames": {
|
|
157
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
158
|
+
},
|
|
159
|
+
"additionalProperties": {
|
|
160
|
+
"type": "object",
|
|
161
|
+
"required": ["command"],
|
|
162
|
+
"additionalProperties": false,
|
|
163
|
+
"properties": {
|
|
164
|
+
"command": { "type": "string", "minLength": 1 },
|
|
165
|
+
"kind": { "enum": ["action", "view"] },
|
|
166
|
+
"context": { "enum": ["home", "scope"] },
|
|
167
|
+
"description": { "type": "string" },
|
|
168
|
+
"args": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": {
|
|
171
|
+
"type": "object",
|
|
172
|
+
"required": ["name"],
|
|
173
|
+
"additionalProperties": false,
|
|
174
|
+
"properties": {
|
|
175
|
+
"name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
|
|
176
|
+
"flag": { "type": "string", "pattern": "^--[a-z][a-z0-9-]*$" },
|
|
177
|
+
"required": { "type": "boolean" },
|
|
178
|
+
"description": { "type": "string" }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
153
185
|
"hooks": {
|
|
154
186
|
"type": "object",
|
|
155
187
|
"properties": {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Architecture reassessment: usable agents with replaceable services
|
|
2
|
+
|
|
3
|
+
Assessment of main `76c0ea4`, September 7, 2026. Requested by Juan after
|
|
4
|
+
operating the Desktop; incorporates Pepe's terminal, shortcut, split and soul
|
|
5
|
+
management feedback. This records the direction and implementation gaps, not a
|
|
6
|
+
claim that every item below has shipped.
|
|
7
|
+
|
|
8
|
+
The requirements authority for this assessment is Juan's September 3
|
|
9
|
+
“Architecture simplification and generlization” in his OATS project KB:
|
|
10
|
+
souls carry instructions and capabilities; a harvester converts ephemeral
|
|
11
|
+
state into knowledge accessible through the selected knowledge capability;
|
|
12
|
+
packages distribute souls and capabilities; OATS constructs and operates
|
|
13
|
+
instances across runtimes and platforms. The private Bookshelf README points
|
|
14
|
+
to September 1's adoption/sovereignty strategy. Its relevant constraint is that
|
|
15
|
+
changing a runtime or service provider must not erase the team's relationships
|
|
16
|
+
or working knowledge. The older August proposals about genomes, clothes and
|
|
17
|
+
turn-record experiments are background, not reasons to expand this release.
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
Keep the existing package and capability-layer mechanism. Correct the places
|
|
22
|
+
where the CLI and GUI bypass it. The architecture is broadly right; the
|
|
23
|
+
operator experience and some service boundaries are incomplete. More
|
|
24
|
+
abstractions will not fix a terminal that cannot accept a screenshot.
|
|
25
|
+
|
|
26
|
+
| Component | Owns | Must not assume |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| OATS kernel | Soul/instance construction, configuration, lifecycle, host placement, scheduling, capability resolution | A particular knowledge provider, messaging service, or GUI |
|
|
29
|
+
| Session backend | Durable terminal, attach/detach, resize, literal input, observation | OATS soul/package semantics or task success |
|
|
30
|
+
| Knowledge capability | Knowledge access and representation; its harvester and promotion policy | Every installation uses OKF or stores memory in the same files |
|
|
31
|
+
| Messaging capability / aweb | Durable messages, identities, event subscriptions and delivery policy | A particular model harness or an open Desktop window |
|
|
32
|
+
| Task capability | Durable work and task semantics | A particular terminal backend |
|
|
33
|
+
| Desktop | Inspect effective configuration; explicit operator actions; terminal input, files, layout | Provider names, SSH commands, or a second lifecycle implementation |
|
|
34
|
+
|
|
35
|
+
Scheduling belongs to OATS, and a scheduled harvest is one use of scheduling.
|
|
36
|
+
Harvesting behavior belongs to the knowledge capability. Starting an agent,
|
|
37
|
+
writing a prompt, and producing reviewed knowledge are different outcomes.
|
|
38
|
+
The UI must retain those distinctions.
|
|
39
|
+
|
|
40
|
+
## What already fits, and what does not
|
|
41
|
+
|
|
42
|
+
`lib/core.mjs` already selects exclusive knowledge/messaging/tasks layers by
|
|
43
|
+
manifest, resolves scoped capability settings, dispatches lifecycle hooks, and
|
|
44
|
+
materializes runtime instructions. Jira and Linear demonstrate that a layer
|
|
45
|
+
can have alternative implementations. OKF's harvester is already an exported
|
|
46
|
+
capability agent. There is no reason to replace this machinery.
|
|
47
|
+
|
|
48
|
+
The remaining coupling is concrete:
|
|
49
|
+
|
|
50
|
+
- The retire receipt reads `hookResults.meta["oats.okf"].harvested`, although
|
|
51
|
+
current OKF does not supply a retire hook. Remove the dead provider-specific
|
|
52
|
+
inference; do not invent successful harvesting at retirement.
|
|
53
|
+
- Remote capability routing recognizes `okf harvest` specifically in
|
|
54
|
+
`bin/oats.mjs` and `lib/servers.mjs`.
|
|
55
|
+
- Desktop harvest actions and scheduled-harvest definitions construct
|
|
56
|
+
`oats okf harvest`; the editor recognizes that exact argv.
|
|
57
|
+
- The “brain” view presents `STATE.md`, `log.md` and `notes/` as universal
|
|
58
|
+
knowledge structure. These are conventions of the current setup.
|
|
59
|
+
|
|
60
|
+
The next service contract should expose the **effective knowledge provider and
|
|
61
|
+
its supported operations for a specific soul/home**. Discovering a capability
|
|
62
|
+
command namespace alone is insufficient: it does not promise a `harvest` verb
|
|
63
|
+
or a shared file layout. A provider may offer harvest, different operations,
|
|
64
|
+
or read-only access. Desktop must show only declared operations and route
|
|
65
|
+
execution through the selected CLI capability. The same resolution must apply
|
|
66
|
+
locally, remotely, and when a scheduled operation runs.
|
|
67
|
+
|
|
68
|
+
Keep that change small: explicit operation metadata, scoped discovery, and one
|
|
69
|
+
invocation route using the existing capability engine. Do not add a plugin
|
|
70
|
+
framework, generic workflow language, or a second knowledge store. Demonstrate
|
|
71
|
+
replaceability with a tiny alternative-provider fixture that uses a different
|
|
72
|
+
command and storage layout; a full second product is unnecessary.
|
|
73
|
+
|
|
74
|
+
## tmux and Herdr
|
|
75
|
+
|
|
76
|
+
The current kernel defaults to a shared tmux session (`pi-agents`) with a
|
|
77
|
+
window per instance. An agent does not require another tmux server. The GUI
|
|
78
|
+
creates a temporary session linking only the selected window. That isolates
|
|
79
|
+
viewers: switching a terminal elsewhere cannot redirect a GUI tab to another
|
|
80
|
+
agent, and an agent exiting cannot silently expose a sibling under its label.
|
|
81
|
+
The `oatsdesk-*` name in Juan's screenshot is this viewer. Its status bar can
|
|
82
|
+
be hidden with a viewer-local setting. Do not alter global tmux settings or
|
|
83
|
+
merge/move live agent sessions to solve a display defect.
|
|
84
|
+
|
|
85
|
+
Herdr 0.8.2 is a separate terminal runtime, not a tmux-compatible superset.
|
|
86
|
+
Its documented direct terminal attachment, socket API, events and SSH support
|
|
87
|
+
are useful. Its semantic agent state comes from detection and/or integrations;
|
|
88
|
+
it is richer evidence, not proof that a particular message was consumed.
|
|
89
|
+
The [socket API](https://herdr.dev/docs/socket-api/) explicitly distinguishes
|
|
90
|
+
agent-state waits from arbitrary command completion. The
|
|
91
|
+
[remote documentation](https://herdr.dev/docs/persistence-remote/) also
|
|
92
|
+
separates a local thin client from running a client entirely on the server;
|
|
93
|
+
only the former can directly bridge the local desktop clipboard.
|
|
94
|
+
|
|
95
|
+
Keep one OATS session contract and both existing adapters for now. Do not add
|
|
96
|
+
another supervisor above them. Qualify Herdr's actual literal multi-line
|
|
97
|
+
input, exact occupant checks, detach, resize, process exit and remote behavior
|
|
98
|
+
before selecting it as the default for new instances. Inspect `pane run`
|
|
99
|
+
implementation before replacing it merely because its name sounds like shell
|
|
100
|
+
execution. Removing tmux is a later deployment choice, not a prerequisite for
|
|
101
|
+
consistent UI or remote agents. Existing tmux agents stay where they are.
|
|
102
|
+
|
|
103
|
+
## Desktop correction sequence
|
|
104
|
+
|
|
105
|
+
1. **Terminal essentials.** Hide viewer chrome, accept dropped files and pasted
|
|
106
|
+
images without pressing Enter, upload remote files to the execution host,
|
|
107
|
+
preserve the destination tab across async work, and show transfer failures.
|
|
108
|
+
Keep a single GUI and bounded viewers. This is the immediate implementation.
|
|
109
|
+
2. **Keyboard and splits.** Restore Ctrl+Tab navigation inside Mac terminals;
|
|
110
|
+
let an already-open terminal fill an empty split without a second attach;
|
|
111
|
+
expose draggable and keyboard-operable separators. Follow up specific
|
|
112
|
+
keyboard reports with real input tests, especially terminal editing keys
|
|
113
|
+
and non-US layouts. App shortcuts must not silently steal terminal edits.
|
|
114
|
+
3. **Souls & capabilities.** Replace the launch-centric roster with a management
|
|
115
|
+
surface showing souls, installed capabilities, effective layer providers,
|
|
116
|
+
source/version, scoped activation and runtime defaults. Inspect and launch
|
|
117
|
+
are distinct actions. Edits use existing CLI operations with the exact scope
|
|
118
|
+
visible; installing a capability must not silently activate it. This is not
|
|
119
|
+
a marketplace or Team Builder project.
|
|
120
|
+
4. **Provider-neutral operations.** Introduce the scoped operation contract
|
|
121
|
+
above, then use it for manual harvest, schedules and knowledge inspection.
|
|
122
|
+
No second hardcoded default is accepted as a generalization.
|
|
123
|
+
5. **Operating rollout.** Enable schedules per team with the owner's learning
|
|
124
|
+
policy. Capture-lock recovery is a separate reliability issue affecting
|
|
125
|
+
unattended harvesting; it does not block arbitrary scheduled wakes.
|
|
126
|
+
|
|
127
|
+
Acceptance must include real Electron file objects, actual terminal bytes,
|
|
128
|
+
remote transfer hashes, split focus/resize without extra PTYs, and a provider
|
|
129
|
+
replacement fixture. Unit tests of mocked argv alone do not establish these
|
|
130
|
+
boundaries. Reuse the existing agents and GUI sparingly; no model is needed to
|
|
131
|
+
exercise attachment transport or terminal layout.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Souls and capabilities in Desktop
|
|
2
|
+
|
|
3
|
+
Selecting a soul opens its details. Launch and Schedule are explicit actions;
|
|
4
|
+
Quick Open and Enter inspect instead of launching. The existing local Files
|
|
5
|
+
browser remains available. It is separate from provider knowledge inspection.
|
|
6
|
+
|
|
7
|
+
The inspector reads the kernel's `oats inspect --json` answer on selection,
|
|
8
|
+
Refresh, or after an explicit mutation. The roster's eight-second poll never
|
|
9
|
+
rescans capabilities or replaces an editor. Workspace changes invalidate old
|
|
10
|
+
responses. Same-named souls are addressed by name plus agents root; instances
|
|
11
|
+
are addressed by their exact home.
|
|
12
|
+
|
|
13
|
+
The Capabilities button inspects workspace defaults, with a member-scope
|
|
14
|
+
selector where a workspace contains several roots. Installed version, source
|
|
15
|
+
and health are separate from effective activation, provenance and settings.
|
|
16
|
+
Enable, explicit disable and return to inheritance call `oats use`; layer-wide
|
|
17
|
+
disable is distinct from excluding a single capability, and is available only
|
|
18
|
+
when inspecting a workspace or member scope, never an individual soul. These changes apply to
|
|
19
|
+
future instances. Existing homes retain their captured bindings and settings.
|
|
20
|
+
|
|
21
|
+
Authored souls expose only the fields the kernel reports as editable. Desktop
|
|
22
|
+
edits runtime, model, backend, YOLO, description and instructions through
|
|
23
|
+
`oats soul set`. Packaged souls remain read-only and explain where their source
|
|
24
|
+
must be changed. Instructions use a private temporary file; the CLI owns remote
|
|
25
|
+
transfer and mutation. Desktop does not modify YAML or resolve capabilities.
|
|
26
|
+
|
|
27
|
+
An instance's action menu opens Knowledge & capabilities. The kernel supplies
|
|
28
|
+
its snapshot, differences from current configuration, and declared provider
|
|
29
|
+
operations. View operations return labeled documents; Desktop renders their
|
|
30
|
+
text and treats remote paths as provenance, never as local files to open. Actions
|
|
31
|
+
without required arguments can run here. Operations requiring arguments explain
|
|
32
|
+
that they need the CLI. No provider is assumed to support harvesting.
|
|
33
|
+
|
|
34
|
+
Schedules store an operation address and exact home with the kernel's generic
|
|
35
|
+
`operation` job kind. The form discovers declared, available actions on demand.
|
|
36
|
+
The server verifies that declaration again at save time, and the kernel resolves
|
|
37
|
+
and validates the provider at execution time. Existing command schedules remain
|
|
38
|
+
visible and runnable, but the GUI does not reverse-parse their argv to edit them.
|
|
39
|
+
|
|
40
|
+
Every capability request requires an exact advertised workspace. Remote requests
|
|
41
|
+
require its saved server registration and the CLI's operations API feature; all
|
|
42
|
+
routing stays in OATS. The consumer never performs SSH or silently substitutes a
|
|
43
|
+
local workspace. The proxy allows the CLI's bounded operation to return its
|
|
44
|
+
receipt before timing out.
|
|
45
|
+
|
|
46
|
+
Validation: scope/identity and remote-route refusal; private instructions and
|
|
47
|
+
failure cleanup; declared schedule actions; stale inspection/save responses;
|
|
48
|
+
provider text rendering; explicit launch and existing runtime flows. Native
|
|
49
|
+
Electron rendering is checked with a temporary fixture frame in the existing
|
|
50
|
+
GUI, without starting a model, agent, or another application instance.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Provider operations and inspection contract
|
|
2
|
+
|
|
3
|
+
Implemented 2026-09-07 on the existing capability engine. The kernel
|
|
4
|
+
resolves providers; a GUI reads one answer and calls the commands below.
|
|
5
|
+
Nothing here names a provider: what a knowledge, messaging or tasks
|
|
6
|
+
capability offers is what its manifest declares.
|
|
7
|
+
|
|
8
|
+
## Manifest: operations
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
"operations": {
|
|
12
|
+
"harvest": { "kind": "action", "command": "harvest", "context": "home", "description": "Promote this instance's notes into its soul" },
|
|
13
|
+
"inspect": { "kind": "view", "command": "inspect", "context": "home", "description": "Show this instance's working knowledge" }
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`command` names one of the manifest's `commands`. `kind` is `action`
|
|
18
|
+
(default) or `view`. `context` is `home` (default; runs in an instance
|
|
19
|
+
home) or `scope` (runs in the config scope). Optional `args` declare
|
|
20
|
+
`{name, flag, required, description}`; the runner passes `--arg name=value`
|
|
21
|
+
pairs as those flags and refuses unknown or missing required ones. A view
|
|
22
|
+
must answer `{ documents: [{ label, kind: "markdown"|"text", path?, text? }],
|
|
23
|
+
summary? }`; the kernel validates that shape and relays it. Paths are
|
|
24
|
+
provenance for the reader; the kernel reads nothing for a view. Validation
|
|
25
|
+
happens when the manifest loads (`docs/capability-manifest.schema.json`).
|
|
26
|
+
|
|
27
|
+
## oats inspect
|
|
28
|
+
|
|
29
|
+
`oats inspect [--dir <scope>] [--soul <name> [--agents-root <abs>]] [--home
|
|
30
|
+
<abs>] [--server <id>] --json` answers, in one envelope: `scope` (context,
|
|
31
|
+
workspace, team, chain, agentsRoots); `souls` (persistent, local and
|
|
32
|
+
packaged, each with runtime defaults, `editable {fields, instructions,
|
|
33
|
+
reason}`, instances, and for the selected soul its `instructions {file,
|
|
34
|
+
text, sha256, bytes, truncated, error}` capped at 256 KiB of bytes on a
|
|
35
|
+
character boundary); `layers` (effective provider per layer); `capabilities`
|
|
36
|
+
(installed state and `health` from the package engine, `missingRequires`,
|
|
37
|
+
and separately `activation {enabled, source, target, level, provenance,
|
|
38
|
+
settings, declaredAt}` plus `operations` with `available` and a `reason`);
|
|
39
|
+
`knowledge` (the effective knowledge provider's operations); `snapshot` and
|
|
40
|
+
`currentConfig` with `--home`; `problems`.
|
|
41
|
+
|
|
42
|
+
A `--home` answer is authoritative for that home: activation, settings,
|
|
43
|
+
layers and operation availability come from the home's captured bindings
|
|
44
|
+
with the currently acquired manifests and current trust, marked `source:
|
|
45
|
+
"snapshot"`; the live config is `currentConfig`, and `snapshot.drift`
|
|
46
|
+
lists activation, settings and integrity differences. The home selects its
|
|
47
|
+
own soul under its own agents root (its recorded work repository may be
|
|
48
|
+
another repository); `--dir`, if given, must be the recorded repository or
|
|
49
|
+
the workspace of that root, and `--agents-root` must be that root
|
|
50
|
+
(`E_HOME_MISMATCH`). Without a home, `--dir` is the config context and
|
|
51
|
+
same-named souls under two member roots need `--agents-root`
|
|
52
|
+
(`E_SOUL_AMBIGUOUS`). The ambient `PI_AGENTS_ROOT` never redirects these
|
|
53
|
+
commands. Integrity scanning happens only in this command.
|
|
54
|
+
|
|
55
|
+
## oats operation run
|
|
56
|
+
|
|
57
|
+
`oats operation run <layer>:<name> (--home <abs> | --soul <name> [--dir
|
|
58
|
+
<scope>] [--agents-root <abs>]) [--arg k=v ...] --json` resolves the
|
|
59
|
+
provider that fills `<layer>` for the home (captured bindings and settings)
|
|
60
|
+
or for the soul in the scope (config), requires the operation to be declared
|
|
61
|
+
(`E_OPERATION_UNKNOWN`), a provider to exist (`E_OPERATION_UNAVAILABLE`,
|
|
62
|
+
also for a home-context operation without `--home`), the executable surface
|
|
63
|
+
to be trusted (`E_CAPABILITY_BLOCKED`) and its `requires` to be on PATH
|
|
64
|
+
(`E_CAPABILITY_REQUIRES`), then runs the provider's own command exactly as
|
|
65
|
+
`oats <ns> <cmd>` would, with cwd and identity set to the selected target
|
|
66
|
+
(`OATS_HOME`, `OATS_INSTANCE`, `OATS_AGENT`, `OATS_SOUL`, `OATS_ROOT`,
|
|
67
|
+
`OATS_CONTEXT`, `OATS_WORKSPACE`, `OATS_OPERATION`, `OATS_SETTINGS`,
|
|
68
|
+
`OATS_CLI_BIN`, team variables) and every ambient identity of the invoking
|
|
69
|
+
process removed. The answer is `{ operation, capability, version, argv,
|
|
70
|
+
cwd, target: {home, instance}|null, result, instance?, home? }`; top-level
|
|
71
|
+
`instance`/`home` appear only when the provider's answer names something it
|
|
72
|
+
launched, never the source home.
|
|
73
|
+
|
|
74
|
+
The receipt must be exactly one JSON-v1 envelope on stdout from a process
|
|
75
|
+
that exits 0. Otherwise the outcome is unconfirmed: `E_OPERATION_TIMEOUT`
|
|
76
|
+
(240 s, below every wrapper) or `E_OPERATION_RESULT` (no valid envelope,
|
|
77
|
+
contaminated output, or a success envelope contradicted by the exit
|
|
78
|
+
status), with `error.details {unconfirmed: true, exit, envelope?, stderr?}`
|
|
79
|
+
carrying what was observed. A provider's own `ok: false` is relayed with
|
|
80
|
+
its code.
|
|
81
|
+
|
|
82
|
+
## Schedules
|
|
83
|
+
|
|
84
|
+
Kind `operation` `{operation: "<layer>:<name>", home}` runs `oats operation
|
|
85
|
+
run <op> --home <home>` as a command job: same admission, tracking and
|
|
86
|
+
reconciliation. An unconfirmed outcome keeps the slot as unknown and any
|
|
87
|
+
name the provider answered is kept for `oats schedule reconcile`.
|
|
88
|
+
|
|
89
|
+
## Mutations
|
|
90
|
+
|
|
91
|
+
`oats use ... --json` answers `{ capability, action: enable|disable|
|
|
92
|
+
layer-none|inherit, target, layer, level, file, settings, before, after
|
|
93
|
+
{..., effective}, remaining?, note?, missingRequires }`. `--inherit`
|
|
94
|
+
removes only the addressed target at this level; other bindings stay and
|
|
95
|
+
are listed. `use none --layer l` is a level statement and takes no soul or
|
|
96
|
+
type. A layer bound to another capability at a level is never overwritten
|
|
97
|
+
(`E_LAYER_BOUND` with the exact remedy).
|
|
98
|
+
|
|
99
|
+
`oats soul set <name> [--dir] [--agents-root] [--runtime] [--model |
|
|
100
|
+
--no-model] [--yolo | --no-yolo] [--backend] [--description |
|
|
101
|
+
--no-description] [--instructions-file <path>] --json` edits only the given
|
|
102
|
+
`soul.yaml` lines and replaces `AGENTS.md`; packaged souls are refused
|
|
103
|
+
(`E_SOUL_READONLY`). The receipt carries before/after and sha256s.
|
|
104
|
+
|
|
105
|
+
## Remote
|
|
106
|
+
|
|
107
|
+
`inspect`, `operation`, `use` and `soul` route with `--server <id>` through
|
|
108
|
+
the saved route. The gate is the destination's `features` list containing
|
|
109
|
+
`operations` and its `operationsApi: 1` (`E_REMOTE_INCOMPATIBLE` before
|
|
110
|
+
anything is sent): `features` describes what a kernel can do locally, which
|
|
111
|
+
is what runs on the host. The probe's `remote` list describes what a CLI
|
|
112
|
+
can ROUTE to a server and is what a GUI checks on the local CLI before
|
|
113
|
+
offering remote actions; it is not a gate on the destination. An explicit `--dir` is the exact member context and
|
|
114
|
+
travels as is; `--home` is its own context; otherwise the registered
|
|
115
|
+
workspace is the scope. Soul instructions travel as bytes on the ssh stdin
|
|
116
|
+
(`--instructions-stdin` on the host), never as a local path.
|
|
117
|
+
|
|
118
|
+
## Replaceability
|
|
119
|
+
|
|
120
|
+
`test/inspect.test.mjs`, `test/operation.test.mjs` and
|
|
121
|
+
`test/operations-routing.test.mjs` use an owned alternative knowledge
|
|
122
|
+
provider (namespace `notes`, one `MEMORY.md`, operations `harvest` and
|
|
123
|
+
`inspect`) and never mention the official provider.
|
package/docs/desktop.md
CHANGED
|
@@ -211,3 +211,19 @@ certificate auto-discovery disabled) and
|
|
|
211
211
|
marked build-verify mode (inventory + strict codesign verification +
|
|
212
212
|
node-pty ABI, no GUI launch); a local
|
|
213
213
|
interactive run may also exercise the launch phase.
|
|
214
|
+
|
|
215
|
+
### Attach files and screenshots
|
|
216
|
+
|
|
217
|
+
Drop a file onto an agent terminal to insert its path into that agent's draft.
|
|
218
|
+
Pasting an image from the clipboard uses the same attachment path. Neither
|
|
219
|
+
operation presses Enter. Text paste continues to use the terminal's normal
|
|
220
|
+
paste behavior. A drop targets the pane under the pointer, including a visible
|
|
221
|
+
pane in a split.
|
|
222
|
+
|
|
223
|
+
Local files are referenced in place. Clipboard images are saved privately in
|
|
224
|
+
Desktop's application-data `attachments` directory and retained so an agent can
|
|
225
|
+
read them later. For remote terminals, Desktop calls the installed CLI's
|
|
226
|
+
`session upload` operation; it inserts the returned path only after the file
|
|
227
|
+
has reached the execution host. Both CLI installations must advertise
|
|
228
|
+
`session-upload`. A failed transfer leaves the draft unchanged and shows an
|
|
229
|
+
error in the terminal. Each drop/paste accepts up to 16 files totaling 25 MB.
|
|
@@ -181,6 +181,27 @@ pane in that exact window. Herdr additionally verifies the original terminal ID.
|
|
|
181
181
|
The broker owns busy/approval policy and must not interpret `submitted` as
|
|
182
182
|
processing acknowledgement.
|
|
183
183
|
|
|
184
|
+
### Attachments
|
|
185
|
+
|
|
186
|
+
A viewer that drops a file or pastes an image gives the agent a path, never
|
|
187
|
+
terminal input. `oats session upload --file <local> --home <abs>` stores a
|
|
188
|
+
copy as a private file under `<home>/.oats-attachments/` (directory 0700,
|
|
189
|
+
file 0600, `name-2` on collision) and answers `{path, bytes, sha256}`; the
|
|
190
|
+
caller pastes `path` into the still-live session itself. With `--server <id>`
|
|
191
|
+
and `--instance <name>` (or `--home`), the same saved route as attach is
|
|
192
|
+
resolved, the remote must list `session-upload` in both its `remote` and
|
|
193
|
+
`features` probe arrays, and the bytes travel on ssh stdin into `oats session
|
|
194
|
+
receive --home <abs> --name <file>` on the execution host. Each side holds
|
|
195
|
+
the whole file in memory up to the 64 MiB kernel bound (this is a bounded
|
|
196
|
+
transfer, not end-to-end streaming); the receiver reads stdin event-driven,
|
|
197
|
+
refuses above the bound before writing, and allocates the destination
|
|
198
|
+
exclusively (`name-2`, `name-3` when taken), so simultaneous uploads of one
|
|
199
|
+
name never overwrite each other and a planted symlink is never followed. The
|
|
200
|
+
attachments directory must be a real directory inside the home. The local
|
|
201
|
+
side refuses the result unless the remote's size and sha256 equal the local
|
|
202
|
+
file's. A remote file is never a local path over SSH. Attachments live and
|
|
203
|
+
die with the home.
|
|
204
|
+
|
|
184
205
|
Capability spawn hooks register a pending home before runtime allocation;
|
|
185
206
|
inspection becomes available once its receipt is persisted. Retire hooks
|
|
186
207
|
unregister after quiescence. The broker must tolerate this lifecycle order and
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# OATS v0.22.13
|
|
2
|
+
|
|
3
|
+
Terminal essentials for the Desktop and one kernel operation behind them:
|
|
4
|
+
attachments reach the agent as a path, never as typed input.
|
|
5
|
+
|
|
6
|
+
## Attachments (kernel)
|
|
7
|
+
|
|
8
|
+
`oats session upload --file <local> --home <abs>` copies a file into the
|
|
9
|
+
instance home's private `.oats-attachments/` directory (0700, file 0600,
|
|
10
|
+
`name-2` when the name is taken) and answers `{path, bytes, sha256}`. With
|
|
11
|
+
`--server <id> --instance <name>` (or `--home`), the same saved route as
|
|
12
|
+
`session attach` is resolved, the remote must advertise the new
|
|
13
|
+
`session-upload` feature, and the bytes travel on ssh stdin into
|
|
14
|
+
`oats session receive --home <abs> --name <file>` on the execution host,
|
|
15
|
+
which reads stdin event-driven, enforces the 64 MiB kernel bound before
|
|
16
|
+
writing anything, allocates the destination exclusively so simultaneous
|
|
17
|
+
uploads never overwrite each other, refuses a symlinked or redirected
|
|
18
|
+
attachments directory, and reports the path only after the bytes are
|
|
19
|
+
synced. The local side refuses the answer unless size and sha256 equal the
|
|
20
|
+
local file's. Each side buffers the whole file up to the bound; a remote
|
|
21
|
+
file is never a local path over SSH. Upload never sends terminal input.
|
|
22
|
+
`oats version --json` lists `session-upload` in `remote` and `features`.
|
|
23
|
+
The CLI's temporary tmux viewer session hides its status line; the agents'
|
|
24
|
+
session and the operator's tmux settings are untouched.
|
|
25
|
+
|
|
26
|
+
## Desktop
|
|
27
|
+
|
|
28
|
+
Drop files or paste clipboard images onto an agent terminal: the paths are
|
|
29
|
+
inserted into the draft with bracketed paste and no Enter, local files in
|
|
30
|
+
place, clipboard images saved privately under the app's data directory, and
|
|
31
|
+
remote terminals uploaded through the installed CLI first (both CLIs must
|
|
32
|
+
advertise `session-upload`; a failed transfer leaves the draft unchanged and
|
|
33
|
+
never inserts a local path). Up to 16 files and 25 MB per drop. The viewer's
|
|
34
|
+
tmux status bar is hidden. Ctrl+Tab stays tab navigation inside terminals
|
|
35
|
+
on macOS while other Ctrl chords stay with the program. An already-open
|
|
36
|
+
terminal fills an empty split without a second attach; separators resize by
|
|
37
|
+
pointer or keyboard. Guide: docs/desktop.md, "Attach files and screenshots".
|
|
38
|
+
|
|
39
|
+
## Design
|
|
40
|
+
|
|
41
|
+
docs/design/2026-09-07-architecture-reassessment.md records the direction:
|
|
42
|
+
keep the package and capability-layer machinery, fix the places where the
|
|
43
|
+
CLI and GUI bypass it, one session contract with both tmux and Herdr
|
|
44
|
+
adapters until Herdr is qualified, and the Desktop correction sequence.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# OATS v0.22.14
|
|
2
|
+
|
|
3
|
+
The same reviewed content as the unpublished v0.22.13 tag, whose hosted
|
|
4
|
+
run failed in one Desktop test pin before anything was published; the
|
|
5
|
+
test now checks the behaviour instead of the source text.
|
|
6
|
+
|
|
7
|
+
Terminal essentials for the Desktop and one kernel operation behind them:
|
|
8
|
+
attachments reach the agent as a path, never as typed input.
|
|
9
|
+
|
|
10
|
+
## Attachments (kernel)
|
|
11
|
+
|
|
12
|
+
`oats session upload --file <local> --home <abs>` copies a file into the
|
|
13
|
+
instance home's private `.oats-attachments/` directory (0700, file 0600,
|
|
14
|
+
`name-2` when the name is taken) and answers `{path, bytes, sha256}`. With
|
|
15
|
+
`--server <id> --instance <name>` (or `--home`), the same saved route as
|
|
16
|
+
`session attach` is resolved, the remote must advertise the new
|
|
17
|
+
`session-upload` feature, and the bytes travel on ssh stdin into
|
|
18
|
+
`oats session receive --home <abs> --name <file>` on the execution host,
|
|
19
|
+
which reads stdin event-driven, enforces the 64 MiB kernel bound before
|
|
20
|
+
writing anything, allocates the destination exclusively so simultaneous
|
|
21
|
+
uploads never overwrite each other, refuses a symlinked or redirected
|
|
22
|
+
attachments directory, and reports the path only after the bytes are
|
|
23
|
+
synced. The local side refuses the answer unless size and sha256 equal the
|
|
24
|
+
local file's. Each side buffers the whole file up to the bound; a remote
|
|
25
|
+
file is never a local path over SSH. Upload never sends terminal input.
|
|
26
|
+
`oats version --json` lists `session-upload` in `remote` and `features`.
|
|
27
|
+
The CLI's temporary tmux viewer session hides its status line; the agents'
|
|
28
|
+
session and the operator's tmux settings are untouched.
|
|
29
|
+
|
|
30
|
+
## Desktop
|
|
31
|
+
|
|
32
|
+
Drop files or paste clipboard images onto an agent terminal: the paths are
|
|
33
|
+
inserted into the draft with bracketed paste and no Enter, local files in
|
|
34
|
+
place, clipboard images saved privately under the app's data directory, and
|
|
35
|
+
remote terminals uploaded through the installed CLI first (both CLIs must
|
|
36
|
+
advertise `session-upload`; a failed transfer leaves the draft unchanged and
|
|
37
|
+
never inserts a local path). Up to 16 files and 25 MB per drop. The viewer's
|
|
38
|
+
tmux status bar is hidden. Ctrl+Tab stays tab navigation inside terminals
|
|
39
|
+
on macOS while other Ctrl chords stay with the program. An already-open
|
|
40
|
+
terminal fills an empty split without a second attach; separators resize by
|
|
41
|
+
pointer or keyboard. Guide: docs/desktop.md, "Attach files and screenshots".
|
|
42
|
+
|
|
43
|
+
## Design
|
|
44
|
+
|
|
45
|
+
docs/design/2026-09-07-architecture-reassessment.md records the direction:
|
|
46
|
+
keep the package and capability-layer machinery, fix the places where the
|
|
47
|
+
CLI and GUI bypass it, one session contract with both tmux and Herdr
|
|
48
|
+
adapters until Herdr is qualified, and the Desktop correction sequence.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# OATS v0.22.15
|
|
2
|
+
|
|
3
|
+
Souls and capabilities become something you inspect and manage, through
|
|
4
|
+
one kernel contract, and knowledge providers declare what they can do.
|
|
5
|
+
|
|
6
|
+
## Provider operations and inspection (kernel)
|
|
7
|
+
|
|
8
|
+
`oats inspect --json` answers everything a GUI needs in one envelope for a
|
|
9
|
+
scope, a selected soul or a running home: souls with runtime defaults,
|
|
10
|
+
editability and instructions; installed capabilities with health from the
|
|
11
|
+
package engine, separately from their effective activation, provenance and
|
|
12
|
+
settings; effective layer bindings; and the operations each provider
|
|
13
|
+
declares, with availability and the reason when unavailable. For a home the
|
|
14
|
+
answer is its captured bindings (with current manifests and trust), the live
|
|
15
|
+
config beside it, and the drift between them. Same-named souls in member
|
|
16
|
+
repositories are addressed by name plus agents root; a home selects its own
|
|
17
|
+
soul under its own root.
|
|
18
|
+
|
|
19
|
+
`oats operation run <layer>:<name>` resolves the provider that fills a layer
|
|
20
|
+
for a home or a soul, checks declaration, trust and host requirements, runs
|
|
21
|
+
the provider's own command in the right place with the right identity, and
|
|
22
|
+
relays its receipt; a view answers labeled documents. Unconfirmed outcomes
|
|
23
|
+
carry what was observed and a scheduled operation keeps its slot until
|
|
24
|
+
reconciled. Manifests declare `operations`. Schedules gain kind
|
|
25
|
+
`operation`. `oats use --json` answers receipts and `--inherit` returns a
|
|
26
|
+
level to inheritance; `oats soul set` edits an editable soul's defaults and
|
|
27
|
+
instructions in place. All four route to a registered server through the
|
|
28
|
+
saved route; the probe advertises `operations` and `operationsApi: 1`. The
|
|
29
|
+
retire receipt no longer implies a harvest. See
|
|
30
|
+
docs/design/operations-contract.md.
|
|
31
|
+
|
|
32
|
+
## oats.okf 1.6.0
|
|
33
|
+
|
|
34
|
+
The official knowledge provider declares `inspect` (a view of STATE.md,
|
|
35
|
+
log.md and pending notes) and `harvest` (the existing action); the catalog
|
|
36
|
+
pins v1.6.0. Existing scopes keep their locked 1.5.2 until their owners
|
|
37
|
+
update them; the GUI then shows no operations for those providers, which is
|
|
38
|
+
the truthful state.
|
|
39
|
+
|
|
40
|
+
## Desktop
|
|
41
|
+
|
|
42
|
+
Souls & capabilities replaces the launch-centric roster: select a soul to
|
|
43
|
+
inspect it, Launch and Schedule are explicit, defaults and instructions are
|
|
44
|
+
editable where the kernel says so, installed capabilities are shown apart
|
|
45
|
+
from activation with enable, disable and inherit at an exact scope, an
|
|
46
|
+
instance's menu opens Knowledge & capabilities, provider views render as
|
|
47
|
+
text, and schedules run declared provider operations. See
|
|
48
|
+
docs/design/2026-09-07-desktop-souls-capabilities.md.
|