@awebai/oats 0.22.19 → 0.23.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 +6 -2
- package/bin/oats.mjs +24 -10
- package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +558 -0
- package/docs/design/2026-09-13-knowledge-and-memory-direction.md +744 -0
- package/docs/design/2026-09-13-knowledge-implementation.md +127 -0
- package/docs/design/2026-09-13-knowledge-location-contract.md +340 -0
- package/docs/design/package-runtime-api.md +177 -3
- package/docs/desktop-cli-api.md +1 -1
- package/docs/execution-targets.md +16 -0
- package/docs/knowledge-capability-authoring.md +98 -0
- package/docs/knowledge-reference/acceptance.md +108 -0
- package/docs/knowledge-reference/adoption.md +61 -0
- package/docs/knowledge-reference/harvester.md +107 -0
- package/docs/knowledge-reference/model.md +84 -0
- package/docs/knowledge-reference/package-craft.md +126 -0
- package/docs/knowledge-reference/provider-mapping.md +77 -0
- package/docs/knowledge-reference/reader-capture.md +87 -0
- package/docs/knowledge-theory.md +20 -6
- package/docs/layers.md +8 -7
- package/docs/oats-config.schema.json +5 -2
- package/docs/release-notes/v0.23.0.md +93 -0
- package/docs/souls-and-instances.md +17 -1
- package/injects/work-directory.md +18 -0
- package/lib/core.mjs +279 -56
- package/lib/schedule.mjs +12 -2
- package/package.json +2 -2
- package/packages/record/README.md +19 -0
- package/packages/record/bin/capture.mjs +96 -48
- package/packages/record/bin/recall.mjs +17 -11
- package/packages/record/bin/record-native-start.mjs +11 -0
- package/packages/record/lib/capture-cc.mjs +82 -27
- package/packages/record/lib/capture-lock.mjs +15 -2
- package/packages/record/lib/formats.mjs +108 -21
- package/packages/record/lib/native-history.mjs +87 -0
- package/packages/record/lib/session-roots.mjs +90 -0
- package/packages/record/lib/session-snapshot.mjs +61 -0
- package/packages/record/lib/sessions-for-home.mjs +88 -56
- package/skills/oats/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -137,8 +137,11 @@ workspace view where reading, editing, Git, builds, tests, and commits happen.
|
|
|
137
137
|
|
|
138
138
|
Work modes: `worktree` (isolated branch for implementation), `checkout` (the
|
|
139
139
|
repository's shared checkout), `attached` (another instance's tree, for
|
|
140
|
-
service agents and reviewers),
|
|
141
|
-
|
|
140
|
+
service agents and reviewers), `workspace` (read-only multi-repository context),
|
|
141
|
+
and explicit `directory` (owned non-Git execution for independent workers;
|
|
142
|
+
`repo` supplies configuration only). Directory mode rejects `--work-dir` and
|
|
143
|
+
`--branch`, and retirement preserves nonempty work in verified recovery storage.
|
|
144
|
+
Placement that cannot be proved fails closed.
|
|
142
145
|
|
|
143
146
|
Provider behavior stays deliberate. Pi runs with ambient skill, context, and
|
|
144
147
|
template discovery curtailed while operator-configured extensions remain
|
|
@@ -307,6 +310,7 @@ forms. Do not hand-edit the lock or installed stores.
|
|
|
307
310
|
- [Migration from OAS](docs/migration-from-oas.md)
|
|
308
311
|
- [Release notes](docs/release-notes/)
|
|
309
312
|
- [Architecture proposal, 2026-09-03](docs/2026-09-03-architecture-proposal.md): components, contracts, and what may be replaced (proposal, not shipped behavior)
|
|
313
|
+
- [Expert-assisted deployment proposal, 2026-09-08](docs/design/2026-09-08-expert-assisted-deployment-proposal.md): setup/repair skills, packaged preparation, live maintenance, and implementation handoff (proposal, not shipped behavior)
|
|
310
314
|
- [iPhone agent management proposal](docs/design/2026-09-07-mobile-agent-management-proposal.md): private server access through Tailscale, mobile UX, and delivery phases (proposal, not shipped behavior)
|
|
311
315
|
|
|
312
316
|
## Contributing
|
package/bin/oats.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { createHash } from "node:crypto";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import { enableTmuxMouse, tmuxConfigPath, tmuxMouseEnabled } from "../lib/tmux-config.mjs";
|
|
23
23
|
import {
|
|
24
|
-
LAYERS, LEGACY_HOME_CAPABILITIES_DIR, OATS_LOCK_FILE, OATS_VERSION, OAS_SCOPE_REMEDY, RETIRED_CAPABILITIES, detectOasScopes, retiredCapabilityReason, configChain, configCapabilityEntries, manifestOperations,
|
|
24
|
+
LAYERS, WORK_MODES, LEGACY_HOME_CAPABILITIES_DIR, OATS_LOCK_FILE, OATS_VERSION, OAS_SCOPE_REMEDY, RETIRED_CAPABILITIES, detectOasScopes, retiredCapabilityReason, configChain, configCapabilityEntries, manifestOperations,
|
|
25
25
|
acquireCapability, restoreCapabilities, marketplaceCapabilities,
|
|
26
26
|
capabilityManifests, capabilityManifest, capabilityMissingRequires, capabilityIntegrity, capabilityTrust, capabilityExecutablePath,
|
|
27
27
|
readCapabilityLocks, writeCapabilityLock,
|
|
@@ -988,7 +988,7 @@ function doctor(dir) {
|
|
|
988
988
|
if (r.injects.length === 0) console.log(" (none)");
|
|
989
989
|
for (const inj of r.injects) console.log(` ${inj.source}: ${shortPath(inj.file)}`);
|
|
990
990
|
|
|
991
|
-
for (const mode of
|
|
991
|
+
for (const mode of WORK_MODES) {
|
|
992
992
|
const wm = resolveWorkMode(ctx, mode);
|
|
993
993
|
console.log(`\nWork mode ${mode}: inject ${wm.inject ? shortPath(wm.inject) : "none"}${wm.setup ? `, setup ${shortPath(wm.setup)}` : ""}`);
|
|
994
994
|
}
|
|
@@ -3532,8 +3532,14 @@ function spawnCmd() {
|
|
|
3532
3532
|
const yolo = yoloFlag();
|
|
3533
3533
|
const backend = valueFlag("backend"), herdrSocket = valueFlag("herdr-socket");
|
|
3534
3534
|
if (backend !== undefined && !["tmux", "herdr"].includes(backend)) bail("E_BAD_ARGS", "--backend must be tmux or herdr");
|
|
3535
|
+
const requestedWork = valueFlag("work");
|
|
3536
|
+
const workDir = valueFlag("work-dir"), branch = valueFlag("branch"), repo = valueFlag("repo");
|
|
3537
|
+
const checkDirectoryOptions = (work) => {
|
|
3538
|
+
if (work === "directory" && (workDir !== undefined || branch !== undefined)) bail("E_BAD_ARGS", "--work directory owns only <home>/work; --work-dir and --branch are not allowed");
|
|
3539
|
+
};
|
|
3540
|
+
checkDirectoryOptions(requestedWork); // before a local soul could be upserted
|
|
3535
3541
|
const name = args[1];
|
|
3536
|
-
if (!name || name.startsWith("--")) bail("E_USAGE", "usage: oats spawn <agent> [--task <text>|--task-file <f>] [--purpose <slug>] [--relation child|sibling|parent|unrelated --relative-to <instance> [--relative-root <agents-root>]] [--parent <instance>] [--repo <r>] [--work worktree|checkout|attached|workspace] [--work-dir <owner-work>] [--runtime pi|claude|codex] [--backend tmux|herdr] [--herdr-socket <path>] [--yolo|--no-yolo] [--model <m>] [--branch <b>] [--instructions-file <f>|--def-file <f>] [--no-launch] [--json]");
|
|
3542
|
+
if (!name || name.startsWith("--")) bail("E_USAGE", "usage: oats spawn <agent> [--task <text>|--task-file <f>] [--purpose <slug>] [--relation child|sibling|parent|unrelated --relative-to <instance> [--relative-root <agents-root>]] [--parent <instance>] [--repo <r>] [--work worktree|checkout|attached|workspace|directory] [--work-dir <owner-work>] [--runtime pi|claude|codex] [--backend tmux|herdr] [--herdr-socket <path>] [--yolo|--no-yolo] [--model <m>] [--branch <b>] [--instructions-file <f>|--def-file <f>] [--no-launch] [--json]");
|
|
3537
3543
|
// Retired boundary flags (maintainer transport ruling): fail LOUDLY before
|
|
3538
3544
|
// ANY side effect — including root discovery and local-agent upsert (an
|
|
3539
3545
|
// --instructions-file spawn must not scaffold/overwrite a local soul before
|
|
@@ -3566,6 +3572,7 @@ function spawnCmd() {
|
|
|
3566
3572
|
note(`(cross-repo: soul "${name}" found at ${shortPath(root)} — instance homes there)`);
|
|
3567
3573
|
}
|
|
3568
3574
|
}
|
|
3575
|
+
checkDirectoryOptions(requestedWork || agent?.work);
|
|
3569
3576
|
// local agents: create/update from raw instructions or a single-file def
|
|
3570
3577
|
if (instrFile || defFile || !agent) {
|
|
3571
3578
|
if (!agent && !instrFile && !defFile) {
|
|
@@ -3651,8 +3658,11 @@ function spawnCmd() {
|
|
|
3651
3658
|
try {
|
|
3652
3659
|
r = spawnInstance(root, agent, {
|
|
3653
3660
|
purpose: flag("purpose"), task: taskText, taskFile: taskFileFlag, relation, relativeTo, relativeRoot,
|
|
3654
|
-
|
|
3655
|
-
|
|
3661
|
+
// Directory execution uses deployment configuration, not an ambient Git
|
|
3662
|
+
// checkout (especially when invoked via --dir from a source instance).
|
|
3663
|
+
repo: (requestedWork || agent.work) === "directory"
|
|
3664
|
+
? (repo ?? agent.repo) : repo || agent.repo || defaultRepo(workspaceOf(root)) || defaultRepo(process.cwd()),
|
|
3665
|
+
work: requestedWork, workDir, runtime: flag("runtime"), backend, herdrSocket, yolo, model: flag("model"), branch,
|
|
3656
3666
|
launchConfig: valueFlag("launch-config"),
|
|
3657
3667
|
launch: !args.includes("--no-launch"),
|
|
3658
3668
|
});
|
|
@@ -3666,7 +3676,7 @@ function spawnCmd() {
|
|
|
3666
3676
|
// model, runtime) is a fact about the selection, not a spawn-mechanism
|
|
3667
3677
|
// failure: it keeps its own code so a GUI can act on it.
|
|
3668
3678
|
if (typeof e?.code === "string" && /^E_LAUNCH_|^E_MODEL_UNKNOWN$|^E_UNSUPPORTED_RUNTIME$/.test(e.code)) { bail(e.code, e.message); throw e; }
|
|
3669
|
-
bail(
|
|
3679
|
+
bail(["E_BAD_ARGS", "E_RELATIVE_AMBIGUOUS"].includes(e.code) ? e.code : "E_SPAWN_FAILED", e.message || e); throw e;
|
|
3670
3680
|
}
|
|
3671
3681
|
// The instance exists from here on: a failed wake save is reported beside
|
|
3672
3682
|
// the full receipt, never hidden, and never causes a second spawn.
|
|
@@ -3863,7 +3873,7 @@ async function paneCmd() {
|
|
|
3863
3873
|
function createCmd() {
|
|
3864
3874
|
const yolo = yoloFlag();
|
|
3865
3875
|
const name = args[1];
|
|
3866
|
-
if (!name || name.startsWith("--")) die("usage: oats create <name> [--local] [--description <d>] [--type <agent-type>] [--repo <r>] [--work worktree|checkout|attached|workspace] [--runtime pi|claude|codex] [--model <m>] [--yolo|--no-yolo] [--instructions-file <f>]");
|
|
3876
|
+
if (!name || name.startsWith("--")) die("usage: oats create <name> [--local] [--description <d>] [--type <agent-type>] [--repo <r>] [--work worktree|checkout|attached|workspace|directory] [--runtime pi|claude|codex] [--model <m>] [--yolo|--no-yolo] [--instructions-file <f>]");
|
|
3867
3877
|
const local = args.includes("--local");
|
|
3868
3878
|
const startDir = dirFlag();
|
|
3869
3879
|
// `create` BOOTSTRAPS a deployment: with no agents/ or local-agents/ yet,
|
|
@@ -3873,14 +3883,16 @@ function createCmd() {
|
|
|
3873
3883
|
// `oats init` (a raw stack trace from ensureRoot). Local and committed souls
|
|
3874
3884
|
// anchor the same way; writeSoul creates the directories.
|
|
3875
3885
|
let root = findRoot(startDir);
|
|
3876
|
-
|
|
3886
|
+
// A configured package-only scope may resolve its future agents root before
|
|
3887
|
+
// that directory exists. Preserve create's bootstrap receipt/message.
|
|
3888
|
+
let bootstrapped = !!root && !existsSync(root) && !existsSync(join(dirname(root), "local-agents"));
|
|
3877
3889
|
if (!root) {
|
|
3878
3890
|
root = join(defaultRepo(startDir) || resolve(startDir), "agents");
|
|
3879
3891
|
bootstrapped = true;
|
|
3880
3892
|
}
|
|
3881
3893
|
const instrFile = flag("instructions-file");
|
|
3882
3894
|
const r = coreCreateAgent(root, {
|
|
3883
|
-
name, local, description: flag("description"), type: flag("type"), repo: flag("repo") || defaultRepo(process.cwd()),
|
|
3895
|
+
name, local, description: flag("description"), type: flag("type"), repo: flag("repo") || (flag("work") === "directory" ? undefined : defaultRepo(process.cwd())),
|
|
3884
3896
|
work: flag("work"), runtime: flag("runtime"), model: flag("model"), yolo,
|
|
3885
3897
|
instructions: instrFile ? readFileSync(instrFile, "utf8") : undefined,
|
|
3886
3898
|
});
|
|
@@ -4661,11 +4673,13 @@ Usage:
|
|
|
4661
4673
|
[--relation child|sibling|parent|unrelated] --relation + --relative-to anchor the
|
|
4662
4674
|
[--relative-to <instance>] new instance to an existing one; --parent X
|
|
4663
4675
|
[--relative-root <agents-root>] disambiguates same-named team anchors
|
|
4664
|
-
[--work worktree|checkout|attached|workspace] = sugar for --relative-to X --relation
|
|
4676
|
+
[--work worktree|checkout|attached|workspace|directory] = sugar for --relative-to X --relation
|
|
4665
4677
|
[--work-dir <owner-work>] [--runtime pi|claude|codex] [--backend tmux|herdr] [--herdr-socket <path>] [--yolo|--no-yolo] [--model <m>] [--branch <b>] child (default: unrelated, top-level)
|
|
4666
4678
|
[--instructions-file <f>|--def-file <f>] [--no-launch] [--json]
|
|
4667
4679
|
with team: declared, unknown local souls
|
|
4668
4680
|
resolve across the team scope's repos
|
|
4681
|
+
directory: owned home/work, config context may
|
|
4682
|
+
be non-Git; rejects --work-dir and --branch
|
|
4669
4683
|
oats retire <instance> [--force] retire an instance (window, hooks,
|
|
4670
4684
|
[--self] [--delete-branch] worktree, home); --self = retire the
|
|
4671
4685
|
[--keep-dir] [--json] CALLING instance: the window dies, then
|