@awebai/oats 0.22.0 → 0.22.2

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.
Files changed (60) hide show
  1. package/README.md +40 -50
  2. package/bin/oats.mjs +242 -22
  3. package/capabilities/oats-authoring/LICENSE +21 -0
  4. package/capabilities/oats-authoring/oats-package.json +11 -0
  5. package/capabilities/oats-authoring/oats.json +4 -4
  6. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +63 -0
  7. package/capabilities/oats-authoring/skills/skill-craft/SKILL.md +109 -0
  8. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +109 -0
  9. package/capabilities/oats-aweb/injects/aweb.md +4 -3
  10. package/capabilities/oats-aweb/oats.json +7 -7
  11. package/capabilities/oats-aweb/skills/LICENSE +21 -0
  12. package/capabilities/oats-aweb/skills/VENDORED.md +26 -0
  13. package/capabilities/oats-aweb/skills/aweb-identity/SKILL.md +201 -0
  14. package/capabilities/oats-aweb/skills/aweb-messaging/SKILL.md +161 -0
  15. package/capabilities/oats-aweb/skills/aweb-messaging/references/messaging-scenarios.md +61 -0
  16. package/capabilities/oats-aweb/skills/aweb-team-membership/SKILL.md +328 -0
  17. package/capabilities/oats-aweb/skills/aweb-team-membership/references/team-membership-reference.md +74 -0
  18. package/capabilities/oats-jira/oats.json +1 -1
  19. package/capabilities/oats-linear/oats.json +1 -1
  20. package/capabilities/oats-okf/agents/{memory-harvest.md → memory-harvest/AGENTS.md} +3 -1
  21. package/capabilities/oats-okf/agents/memory-harvest/soul.yaml +6 -0
  22. package/capabilities/oats-okf/bin/oats-okf.mjs +201 -54
  23. package/capabilities/oats-okf/injects/okf.md +7 -0
  24. package/capabilities/oats-okf/oats.json +5 -2
  25. package/capabilities/oats-okf/skills/memory-harvest/SKILL.md +42 -1
  26. package/capabilities/oats-review/oats.json +1 -1
  27. package/docs/2026-09-03-architecture-proposal.md +642 -0
  28. package/docs/execution-targets.md +181 -0
  29. package/docs/first-team-demo.md +87 -0
  30. package/docs/first-team.md +179 -0
  31. package/docs/implementation.md +14 -1
  32. package/docs/integrations.md +83 -65
  33. package/docs/layers.md +356 -80
  34. package/docs/migration-from-oas.md +80 -116
  35. package/docs/oats-config.schema.json +1 -0
  36. package/docs/operating-team-migration.md +217 -0
  37. package/docs/release-notes/v0.22.1.md +106 -0
  38. package/docs/release-notes/v0.22.2.md +69 -0
  39. package/docs/servers.md +94 -0
  40. package/docs/souls-and-instances.md +30 -3
  41. package/lib/core.mjs +626 -415
  42. package/lib/herdr.mjs +95 -0
  43. package/lib/servers.mjs +436 -0
  44. package/lib/session-input.mjs +78 -0
  45. package/lib/session-viewer.mjs +51 -0
  46. package/package-catalog.json +2 -2
  47. package/package.json +1 -1
  48. package/packages/record/README.md +76 -16
  49. package/packages/record/bin/capture.mjs +59 -3
  50. package/packages/record/bin/recall.mjs +67 -1
  51. package/packages/record/docs/turn-record-sot.md +1 -1
  52. package/packages/record/lib/sessions-for-home.mjs +130 -0
  53. package/packages/record/lib/store.mjs +207 -43
  54. package/skills/oats/SKILL.md +6 -2
  55. package/capabilities/oats-aweb/package.json +0 -20
  56. package/capabilities/oats-jira/package.json +0 -25
  57. package/capabilities/oats-linear/README.md +0 -234
  58. package/capabilities/oats-linear/package.json +0 -29
  59. package/capabilities/oats-linear/test/oats-linear.test.mjs +0 -168
  60. package/capabilities/oats-okf/package.json +0 -22
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: integration-authoring
3
+ description: >-
4
+ Route custom OATS capability-package and integration work to the framework's
5
+ integrations expert. Use when building, adapting, or debugging a reusable
6
+ capability, new task/messaging/knowledge integration, oats.json manifest,
7
+ lifecycle hook, or operational command—not merely activating an existing
8
+ package. Triggers: "custom integration", "capability package", "integrate
9
+ our tracker", "new messaging integration", "write an oats.json".
10
+ ---
11
+
12
+ # Capability and integration authoring — delegate
13
+
14
+ A capability package may ship skills, instance instructions, requirements,
15
+ namespaced commands, and approved hooks. An integration is the constrained
16
+ subtype implementing exactly one fundamental layer. Building either requires
17
+ manifest, security, targeting-boundary, collision, and probe discipline; use
18
+ the framework's **integrations-expert** soul rather than improvising.
19
+
20
+ If the user only wants an existing package, use:
21
+
22
+ ```bash
23
+ oats install <source> # external acquisition + exact lock; inactive
24
+ oats trust <id> # only if commands/hooks exist
25
+ oats use <id> --global|--type <t>|--soul <s>
26
+ ```
27
+
28
+ ## 1. Verify the expert is available
29
+
30
+ Run `oats status` and confirm the deployment can resolve the `integrations-expert` soul. If it is absent, ask the human which OATS framework deployment owns reusable package work; never locate or import private kernel files.
31
+
32
+ ## 2. Spawn the expert against the user's repository
33
+
34
+ ```bash
35
+ oats spawn integrations-expert \
36
+ --purpose <package-slug> \
37
+ --repo <users-workspace-or-repo> \
38
+ --work checkout \
39
+ --task '<capability intent; layer if any; skills/instructions/commands/hooks; external tools; desired global/type/soul targets; distribution path>'
40
+ ```
41
+
42
+ Use `--relation child --relative-to <your-instance>` only when the documented workflow makes the expert your child; otherwise leave the operator-origin spawn unrelated. The work tree is the user's repository, where a config-owned local package belongs under `.agents/capabilities/owned/<name>/`. A framework contribution belongs under `capabilities/<name>/` in the framework worktree; an independently published package uses its own repository.
43
+
44
+ ## 3. Brief the design boundary
45
+
46
+ Tell the expert:
47
+
48
+ - whether it is additive or implements exactly one of knowledge/messaging/tasks;
49
+ - external requirements and executable surfaces;
50
+ - intended distribution and version/compatibility;
51
+ - desired config-owned targets and settings; and
52
+ - expected skill/instruction/scaffold collisions.
53
+
54
+ Targets never belong in the manifest. The expert must test exact pi/Claude
55
+ instance materialization, generated instructions, lock/trust behavior,
56
+ command gating, deterministic hooks, and scaffold ownership as applicable.
57
+
58
+ ## 4. Hand off
59
+
60
+ Report the tmux window (`tmux attach -t pi-agents`). The expert follows its
61
+ package/integration craft, runs a scaffold-only probe, and leaves acquisition
62
+ and activation commands for the user. Its durable lessons harvest back into
63
+ its soul.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: skill-craft
3
+ description: >-
4
+ How to create, evaluate, and maintain agent skills (SKILL.md files per the
5
+ Agent Skills standard). Use when writing a new skill, improving or debugging
6
+ an existing one (skill not triggering, agent ignoring instructions, skill too
7
+ long), turning a repeated procedure or correction into a skill, deciding
8
+ whether knowledge belongs in a skill versus the knowledge base versus
9
+ AGENTS.md, bundling scripts into skills, or evaluating whether a skill
10
+ actually helps. Based on the agentskills.io creator guides and Anthropic
11
+ best practices.
12
+ ---
13
+
14
+ # Skill craft — create, evaluate, maintain
15
+
16
+ A skill is a directory with a `SKILL.md` (YAML frontmatter + markdown body),
17
+ optionally `scripts/`, `references/`, `assets/`. Agents load only `name` +
18
+ `description` at startup; the body loads **only when the description matches
19
+ the task** — the description carries the entire burden of triggering.
20
+
21
+ ## Where does this knowledge belong? (decide first)
22
+
23
+ - **Repeatable procedure** ("how to do X, again and again") → **skill**.
24
+ - **Declarative fact/decision/lesson** ("what is true and why") → **OKF
25
+ concept** in the knowledge base (see `okf` skill). Skills may reference
26
+ concepts for the why.
27
+ - **Applies to every session of this agent** (role, boundaries, core workflow)
28
+ → **AGENTS.md** (see `soul-craft`). Rule of thumb: AGENTS.md is loaded
29
+ always — keep it minimal; skills load on demand — put domain workflows there.
30
+
31
+ ## Creating a skill
32
+
33
+ **Ground it in real expertise — never generate from thin air.** The valuable
34
+ content is what a capable model *doesn't* already know: your APIs, your
35
+ conventions, the corrections you had to make. Best sources: a hands-on task
36
+ you just completed (extract the steps that worked, the corrections given, the
37
+ formats used), runbooks, review comments, real failures and their fixes. A
38
+ skill with generic content ("handle errors appropriately") is worthless — cut
39
+ or ground it.
40
+
41
+ **Frontmatter rules** (spec + hard-won):
42
+ - `name`: lowercase alphanum + hyphens, ≤64 chars, **must match the directory
43
+ name**, no leading/trailing/double hyphens.
44
+ - `description`: ≤1024 chars, non-empty. ⚠️ **Use a `>-` block scalar if it
45
+ contains any `: ` colon-space** — an unquoted colon breaks YAML parsing and
46
+ the skill silently fails to load. Verify new skills actually load.
47
+
48
+ **Write the description for triggering** (it's the only thing the agent sees
49
+ before deciding):
50
+ - Imperative: "Use when..." not "This skill does...".
51
+ - Name the **user intents** it serves, not the implementation. Include
52
+ trigger phrases users actually say, and cover cases where they don't name
53
+ the domain ("even if they don't mention X").
54
+ - Precise beats broad: an over-broad description fires on near-miss tasks
55
+ and pollutes context.
56
+
57
+ **Write the body for a loaded context window** — it competes with everything
58
+ else once loaded:
59
+ - **Only what the agent would get wrong without it.** For every line ask:
60
+ "would removing this cause mistakes?" No → cut.
61
+ - ≤500 lines / ~5k tokens. Larger → move detail to `references/` and tell the
62
+ agent **when** to load each file ("read references/errors.md if the API
63
+ returns non-200"), not just that it exists.
64
+ - **Defaults, not menus**: pick one tool/approach, mention alternatives in
65
+ one line. Match prescriptiveness to fragility: fragile sequences get exact
66
+ commands ("run exactly this"); judgment tasks get goals + why.
67
+ - Procedures over answers: teach the approach that generalizes, with one
68
+ concrete worked example.
69
+ - **Gotchas section** — often the highest-value part: concrete corrections to
70
+ mistakes the agent *will* make ("the /health endpoint lies; use /ready").
71
+ - For multi-step workflows: an explicit checklist. For fragile output: a
72
+ template (agents pattern-match better than they follow prose). For
73
+ correctness-critical work: a validation loop (do → validate → fix → repeat)
74
+ or plan-validate-execute with a validator script.
75
+
76
+ **Scripts**: when you see an agent reinventing the same logic across runs,
77
+ write it once, test it, bundle it in `scripts/`, and reference it from the
78
+ body with exact invocations. Prefer zero-dependency scripts; pin versions for
79
+ `npx`/`uvx` one-offs. Scripts should print errors an agent can self-correct
80
+ from ("field X not found — available: a, b, c").
81
+
82
+ ## Evaluating (before trusting)
83
+
84
+ - **Trigger check**: draft ~10 realistic prompts that *should* fire the skill
85
+ (varied phrasing, some not naming the domain) and ~10 near-misses that
86
+ *shouldn't* (share keywords, need something else). Run them; the skill
87
+ triggered if its body was loaded. Fix the description, not the body, for
88
+ trigger failures.
89
+ - **Output check**: run 2-3 real tasks **with and without** the skill. If
90
+ with-skill isn't clearly better, the skill isn't earning its context — cut
91
+ or sharpen it. Read execution traces, not just outputs: wasted steps mean
92
+ vague instructions, inapplicable instructions being followed, or menus
93
+ without defaults.
94
+
95
+ ## Maintaining
96
+
97
+ - **Every correction is a candidate gotcha.** When a human (or reviewer)
98
+ corrects an agent following the skill, add the correction to the gotchas —
99
+ this is the single best maintenance loop.
100
+ - Treat skills like code: prune on every edit; if the agent ignores a rule,
101
+ the skill is probably too long and the rule is drowning. Test behavior
102
+ changes by observing runs, not by rereading the text.
103
+ - Never let a skill grow past one coherent unit of work — split like you'd
104
+ split a function.
105
+ - Log skill changes in the soul's `knowledge/log.md` (`**Update**: skills/x —
106
+ added gotcha about …`) so knowledge history and skill history stay one
107
+ timeline. Knowledge maintenance and skill maintenance are the same duty:
108
+ declarative lessons go to OKF concepts, procedural lessons go to skills,
109
+ and each should link to the other.
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: soul-craft
3
+ description: >-
4
+ How to author and maintain an agent's soul — its AGENTS.md/CLAUDE.md
5
+ operating doc, soul.yaml config, and the balance between AGENTS.md, skills,
6
+ and the OKF knowledge base. Use when creating a new agent (writing its first
7
+ AGENTS.md), refining an existing soul that underperforms (agent ignores
8
+ instructions, drifts from its role, bloated operating doc), reviewing a
9
+ soul's setup, or deciding what goes in AGENTS.md versus a skill versus
10
+ knowledge. Based on the agents.md standard and Anthropic CLAUDE.md guidance.
11
+ ---
12
+
13
+ # Soul craft — author and maintain agent operating docs
14
+
15
+ A soul's `AGENTS.md` is loaded **every session of
16
+ every instance**. It is the most expensive real estate in the agent's context:
17
+ everything in it taxes every task, relevant or not. The craft is keeping it
18
+ minimal and pushing everything else to on-demand layers.
19
+
20
+ **Canonical files:** `AGENTS.md` and `.agents/skills/` are the canonical
21
+ sources; `CLAUDE.md` and `.claude/skills` must always be relative symlinks to
22
+ them, never independent files (the spawner creates these links — if you find a
23
+ real CLAUDE.md file diverging from AGENTS.md, that's a defect: merge and relink).
24
+
25
+ ## The three-layer rule
26
+
27
+ | Layer | Loaded | Belongs there |
28
+ |---|---|---|
29
+ | **AGENTS.md** | always | Role, boundaries, the default workflow, memory pointers — only what applies to *every* session |
30
+ | **skills/** | on demand (description match) | Domain workflows, repeatable procedures ("how") — see `skill-craft` |
31
+ | **knowledge/** | on demand (index-first) | Facts, decisions, lessons ("what/why") — format per the knowledge integration (default okf) |
32
+
33
+ The test for every AGENTS.md line: **"would removing this cause mistakes in
34
+ most sessions?"** No → move it to a skill or a knowledge concept, or cut it.
35
+ Bloated operating docs cause agents to ignore the rules that matter — a rule
36
+ being ignored is usually a symptom of too many rules.
37
+
38
+ ## Writing a soul's AGENTS.md
39
+
40
+ Structure that works (keep the whole thing short — a screen or two):
41
+
42
+ 1. **Role, one paragraph.** Who this agent is, what it owns, where it stops.
43
+ Boundaries beat capabilities: "you never merge", "you never modify the
44
+ assignee", "UI belongs to the ui agent" prevent more damage than feature
45
+ lists add value.
46
+ 2. **Operating loop.** The default shape of a work session — for a developer:
47
+ read ticket → plan in STATE.md → implement in ./work → verify → commit →
48
+ review loop → hand off. Concrete, not aspirational.
49
+ 3. **Verification.** How this agent checks its own work: the build/test/lint
50
+ commands that must pass, what "done" means. An agent with a check it can
51
+ run closes its own loop; without one, "looks done" is the only signal.
52
+ Include exact commands the agent can't guess (`make test-unit`, not
53
+ "run the tests").
54
+ 4. **Memory pointers.** Where its knowledge and state live (knowledge base
55
+ index, STATE.md discipline). Point, don't duplicate — the protocol lives
56
+ with your knowledge integration (default okf: the memory-harvest skill).
57
+ 5. **Escalation.** When to stop and ask the human or coordinator: the
58
+ human-gate triggers (security, authz, migrations, contract breaks),
59
+ plus "report to your spawner, don't self-fix" for infrastructure faults.
60
+
61
+ Style rules (from the agents.md standard + field experience):
62
+ - Write commands, not prose: `pnpm vitest run -t "<name>"` beats "run the
63
+ relevant test".
64
+ - Include only what can't be inferred from the repo: conventions that differ
65
+ from defaults, env quirks, etiquette (branch naming, PR format).
66
+ - Exclude: standard language conventions, file-by-file codebase tours, API
67
+ docs (link instead), anything that changes weekly (that's knowledge),
68
+ self-evident advice ("write clean code").
69
+ - Emphasis (**IMPORTANT**, YOU MUST) sparingly — it works, and it stops
70
+ working when everything is emphasized.
71
+ - The repo's own AGENTS.md (in ./work) covers repo mechanics — the soul doc
72
+ covers the *role*. Don't duplicate the repo doc; instruct reading it.
73
+
74
+ ## soul.yaml
75
+
76
+ Keep honest: `repo` (what it works on), `work` (worktree for builders,
77
+ checkout for reviewers/coordinators), `runtime`, `model` (only pin when the
78
+ role needs a specific one — reviewers on a different model than authors),
79
+ `description` (one line; shows in rosters and pickers).
80
+
81
+ ## Maintaining a soul
82
+
83
+ - **Change AGENTS.md rarely and deliberately** — it defines the agent. The
84
+ bar: a change in how the agent fundamentally operates, proven by instance
85
+ experience. Day-to-day lessons go to knowledge; procedures to skills.
86
+ - When an instance repeatedly misbehaves, diagnose in order: (1) is the rule
87
+ drowning in a bloated doc? → prune the doc; (2) is it ambiguous? → sharpen
88
+ with a command or example; (3) is it missing? → add it, minimally. Test by
89
+ observing the next instance's behavior, not by rereading.
90
+ - **Prune on every edit.** Adding a line? Look for two to cut.
91
+ - Log every soul change in `knowledge/log.md` (`**Update**: AGENTS.md — …`)
92
+ so the soul's evolution is reconstructible.
93
+ - Agents never rewrite their own role or safety boundaries; soul changes that
94
+ alter behavior go through the human (or a documented review workflow).
95
+ - Periodic review (worth doing when spawning feels off): does the role still
96
+ match reality? Do skills cover the recurring procedures? Is the knowledge
97
+ index current? Are the verification commands still correct?
98
+
99
+ ## Bootstrapping a new soul
100
+
101
+ Fastest path to a *grounded* soul (never write one from imagination):
102
+ 1. Do (or supervise) the role's work once in a plain session, noting
103
+ corrections, commands, and conventions as you go.
104
+ 2. Distill: role/boundaries/loop/verification/escalation → AGENTS.md;
105
+ repeated procedures → first skills; facts and decisions → first knowledge
106
+ concepts.
107
+ 3. Spawn an instance on a real task; watch where it stumbles; fold the
108
+ corrections back (doc, skill gotcha, or concept — per the three-layer rule).
109
+ Two rounds of this beat any amount of upfront authoring.
@@ -41,9 +41,10 @@ Aliases are instance names (e.g. `dev-coordinator-1`). Discovery:
41
41
  lists the aweb team across machines.
42
42
 
43
43
  **Never sleep, poll, or busy-wait for another agent's reply.** Send your
44
- message, finish your turn, and go idle — the aweb channel awakens your
45
- session the moment mail or chat arrives (you saw `✓ aweb connected` at
46
- startup). A `sleep N; aw mail inbox` loop burns tokens, delays the reply,
44
+ message, finish your turn, and go idle when a delivery channel is configured
45
+ (you saw `✓ aweb connected` at startup). Native Codex has no aweb channel:
46
+ check inbox and pending chat at task boundaries or when the operator asks,
47
+ as described in TASK.md; incoming messages alone will not wake that session. A `sleep N; aw mail inbox` loop burns tokens, delays the reply,
47
48
  and adds nothing. An empty `aw mail inbox` means no UNREAD mail — not that
48
49
  messages were lost.
49
50
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "capability": "oats.aweb",
3
3
  "command": "aweb",
4
- "version": "1.8.0",
4
+ "version": "1.9.0",
5
5
  "compatibility": {
6
- "oats": ">=0.6.2"
6
+ "oats": ">=0.19.0"
7
7
  },
8
8
  "layer": "messaging",
9
9
  "description": "Messaging layer via aweb: per-instance team identities + native aw mail/chat skills + cross-machine team roster.",
@@ -16,21 +16,21 @@
16
16
  {
17
17
  "runtime": "pi",
18
18
  "package": "npm:@awebai/pi",
19
- "why": "the aweb channel extension for pi sessions \u2014 real-time mail/chat awakenings; without it a pi instance can send with `aw` but is never woken by incoming messages",
19
+ "why": "the aweb channel extension for pi sessions — real-time mail/chat awakenings; without it a pi instance can send with `aw` but is never woken by incoming messages",
20
20
  "install": "https://aweb.ai/docs (installed into pi with `pi install npm:@awebai/pi`)"
21
21
  },
22
22
  {
23
23
  "runtime": "claude",
24
24
  "package": "aweb-channel@awebai-marketplace",
25
25
  "marketplace": "awebai/claude-plugins",
26
- "why": "the aweb channel plugin for Claude Code sessions \u2014 real-time mail/chat awakenings; without it a Claude instance can send with `aw` but is never woken by incoming messages",
26
+ "why": "the aweb channel plugin for Claude Code sessions — real-time mail/chat awakenings; without it a Claude instance can send with `aw` but is never woken by incoming messages",
27
27
  "install": "https://aweb.ai/docs (installs the awebai marketplace and the aweb-channel plugin into Claude Code)"
28
28
  }
29
29
  ],
30
30
  "skills": [
31
- "node_modules/@awebai/pi/skills/aweb-messaging",
32
- "node_modules/@awebai/pi/skills/aweb-team-membership",
33
- "node_modules/@awebai/pi/skills/aweb-identity"
31
+ "skills/aweb-messaging",
32
+ "skills/aweb-team-membership",
33
+ "skills/aweb-identity"
34
34
  ],
35
35
  "inject": "injects/aweb.md",
36
36
  "commands": {
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Juan Reyero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,26 @@
1
+ # Vendored aweb Agent Skills
2
+
3
+ These reviewed resources are vendored from the MIT-licensed aweb repository:
4
+
5
+ - Repository: <https://github.com/awebai/aweb.git>
6
+ - Upstream package: `@awebai/pi@0.2.3`
7
+ - Tag: `pi-v0.2.3`
8
+ - Commit: `812bdeb1be8ed99dbd339a910a153e7b802501d4`
9
+ - Registry integrity: `sha512-SnCT+5Ybh57G7+zwlfw6QRgAoyAVkyhcgRqIPPx47e+UcJdi5REXw9td806LveLEKAx0CwFTyxOInPH6mfs4EA==`
10
+ - License: MIT; see [`LICENSE`](LICENSE)
11
+
12
+ Vendored trees:
13
+
14
+ - `aweb-messaging/`
15
+ - `aweb-team-membership/`
16
+ - `aweb-identity/`
17
+
18
+ To update, check out the named upstream repository at the intended reviewed commit, update the constants in `scripts/sync-vendored-skills.mjs`, then run from this repository root:
19
+
20
+ ```bash
21
+ node scripts/sync-vendored-skills.mjs --source /path/to/aweb
22
+ npm test
23
+ git diff -- capabilities/oats-aweb/skills
24
+ ```
25
+
26
+ The sync command refuses a checkout whose `HEAD` differs from its pinned commit. Review the complete generated diff, upstream license, and triggering descriptions before changing the recorded version/ref. Runtime acquisition never fetches these resources.
@@ -0,0 +1,201 @@
1
+ ---
2
+ name: aweb-identity
3
+ description: This skill should be used when working with an aweb identity itself — the Ed25519 signing keypair, E2E encryption keys, `did:key` and `did:aw`, the public AWID registry, local versus global identities, custodial versus self-custodial custody, what `aw init` does to a directory, addressability (a global identity's address and route), `inbound_mode` delivery policy, contacts, key rotation, and identity-level workspace diagnostics. Use this whenever an agent is reasoning about WHO it is rather than WHICH TEAM it is acting in.
4
+ allowed-tools: "Bash(aw *)"
5
+ ---
6
+
7
+ # aweb Identity
8
+
9
+ Use this skill when the question is about the agent's own identity — its keys, custody model, address, inbound delivery policy, contacts, or key rotation. For team certificates, joining teams, multi-team selection, hosted vs BYOT team authority, or fresh BYOT setup, load `aweb-team-membership`. For day-to-day work coordination, load `aweb-coordination`. For mail/chat response policy, load `aweb-messaging`.
10
+
11
+ ## Foundations
12
+
13
+ Vocabulary used throughout this skill and referenced by sibling skills. Read once; refer back as needed.
14
+
15
+ - **Signing keypair** — every aweb identity is an Ed25519 keypair. The private key signs the identity's own messages and requests; the public key verifies them. Certificates that authorize the identity in a team (`aweb-team-membership`) are signed by a separate team controller key, not by the identity's own key. Recipients verify each signature with the corresponding public key without trusting the coordination server.
16
+ - **Encryption keypair** — E2E message v2 uses a separate identity encryption keypair for decrypting message content. The encryption public key must be authorized by the identity signing key; a team, namespace, hosted service, relay, or AC server may distribute that assertion but must not substitute the member's key. Signing keys authenticate; encryption keys decrypt.
17
+ - **`did:key`** — the public key encoded as a DID, e.g. `did:key:z6Mk...`. Identifies the current signing key.
18
+ - **`did:aw`** — a stable identity DID kept in the public AWID registry. Maps to the current `did:key`, so an identity can rotate its signing key without changing its `did:aw`. Only global identities have a `did:aw`.
19
+ - **AWID** (publicly readable at `awid.ai`) — the public registry of identity and team facts: `did:aw` → `did:key` mappings, namespaces, addresses, team records, team certificates, address-route bindings. Anyone can verify against AWID without trusting aweb.
20
+ - **Namespace** — usually a DNS domain (e.g. `acme.com`) registered in AWID, controlled by a namespace controller keypair. Addresses are scoped under a namespace.
21
+ - **Local identity** — workspace-bound, alias-based, no public continuity guarantee. Only meaningful within its team and machine.
22
+ - **Global identity** — durable, registered with AWID, has both `did:key` and `did:aw`, can hold one or more public addresses (`<namespace>/<name>`). Survives key rotation, moves across machines.
23
+ - **Custodial vs self-custodial** — *self-custodial* means the local machine holds the private key in `.aw/signing.key`. *Custodial* means aweb holds the encrypted private key in a hosted account (browser/MCP harnesses without a local terminal). Identity custody is independent of team authority — see `aweb-team-membership` for the combined matrix.
24
+
25
+ ## Identity files in `.aw/`
26
+
27
+ A workspace can hold any combination of these. For team-related files (`teams.yaml`, `team-certs/`), see `aweb-team-membership`.
28
+
29
+ - `signing.key` — Ed25519 private key for self-custodial workspaces. If absent, this directory has no local signing identity. Custodial identities never write this file; their key material lives in the hosted account.
30
+ - `encryption.yaml` and `encryption-keys/` — local E2E message-decryption keyring. `encryption.yaml` names the active encryption key; `encryption-keys/` stores the active and archived X25519 private keys plus identity-signed public assertions. Back these up with the workspace. Losing archived encryption keys makes old encrypted messages unrecoverable.
31
+ - `workspace.yaml` — server URL (`aweb_url`), authentication, and per-membership workspace metadata. Binds this directory to one aweb coordination server. Does NOT hold the active-team selection (that's in `teams.yaml`).
32
+
33
+ ## `aw init` vs `aw id create` — workspace onboarding vs identity-only
34
+
35
+ These two commands look similar and are not interchangeable. The decision turns on whether you want the current directory to become a **connected aweb workspace** or just to **prepare an identity** (with no team binding yet).
36
+
37
+ - **`aw id namespace prepare-controller --domain <domain>`** — creates or reuses the local namespace controller key under `~/.awid/controllers/` and prints the `_awid.<domain>` DNS TXT value. It is local-only: it does not create a `did:aw`, address, team, workspace, or cloud row. Tell the human to keep `~/.awid` safe and backed up; this key controls the namespace.
38
+ - **`aw id namespace check-txt --domain <domain>`** — read-only DNS propagation check. It verifies that `_awid.<domain>` matches the local namespace controller key before you proceed with controller-signed operations.
39
+ - **`aw id create --domain <domain> --name <name>`** — creates a standalone global identity (`did:key` + `did:aw` + DNS-backed address) and registers it in AWID. Writes `.aw/identity.yaml` and `.aw/signing.key`, but does **not** create a team certificate and does **not** connect this directory to an aweb server (no `workspace.yaml` server binding, no `teams.yaml` membership entry, no `team-certs/*.pem`). Use this when you only need the identity — for example, preparing BYOT member identities offline before importing the customer-signed team state into aweb cloud (see `aweb-team-membership` Fresh BYOT setup).
40
+
41
+ - **`aw init`** — workspace onboarding. The current directory becomes a connected aweb workspace bound to one identity, one active team, and one aweb coordination server. Three onboarding flows are supported:
42
+ 1. **Connect with an existing team certificate** — when `.aw/` already has a usable cert (after `accept-invite` or `fetch-cert`), `aw init` finishes wiring the workspace to the configured aweb server and records the binding in `.aw/workspace.yaml`. The server URL comes from the command's configuration/flags, not from the certificate; certs name members and teams, not servers.
43
+ 2. **Hosted aweb.ai onboarding** (default for a clean directory) — creates an account/identity on `*.aweb.ai` and binds the directory to it.
44
+ 3. **`--byod`** — onboards under a customer-owned domain instead of hosted aweb.ai. This still creates a workspace binding and a team (`default:<domain>`) on app.aweb.ai. `--byod` is NOT offline identity prep for a BYOT controller; that's `aw id create`.
45
+ - **`aw init --global`** (with or without `--byod`) — creates an addressed self-custodial global identity AND wires the workspace. The workspace half is what makes this different from `aw id create`. Do not reach for `aw init --global` when you want only an identity.
46
+
47
+ `aw init` updates the `aweb` section of `AGENTS.md` / `CLAUDE.md` by default; pass `--do-not-touch-agents-md` to skip. It refuses to overwrite an existing identity in `.aw/`.
48
+
49
+ When deciding which to run:
50
+
51
+ - "I want this directory to start coordinating with a team" → `aw init` (one of the three flows above).
52
+ - "I want to prepare namespace authority for a BYOT setup" → `aw id namespace prepare-controller`, publish the `_awid.<domain>` TXT, then `aw id namespace check-txt`.
53
+ - "I want to mint an identity I'll later attach to a BYOT team via controller-signed facts" → after the namespace TXT checks out, use `aw id create`. Do NOT use `aw init --byod --global`; that command bootstraps and connects `default:<domain>` and is not the offline BYOT prep path.
54
+
55
+ ## Custodial vs self-custodial in practice
56
+
57
+ | Custody | Where the private key lives | How rotation works | Typical harness |
58
+ | --- | --- | --- | --- |
59
+ | Self-custodial | `.aw/signing.key` on the agent's machine | Local: `aw id rotate-key` | Terminal CLI (Claude Code, Codex, Pi runtime) |
60
+ | Custodial | Identity signing key material is held in the hosted aweb account (not a local E2E message-decryption key) | Cloud-account operation (no local CLI command rotates a custodial key) | Browser/MCP agents on Claude.ai, ChatGPT, Claude Desktop |
61
+
62
+ A self-custodial agent has full control over its key — and full responsibility for backups. A custodial agent inherits aweb's account-level recovery story.
63
+
64
+ ## E2E encryption key boundary
65
+
66
+ The normative E2E contract is `docs/e2e-messaging-contract.md`. Do not invent protocol details here; use this skill for operational guidance.
67
+
68
+ For local E2E messaging, the self-custodial client needs both identity signing material and local encryption private keys. Back up the active encryption private key and archived encryption private keys with the same seriousness as `.aw/signing.key`: losing archived encryption keys makes historical encrypted messages unrecoverable. AC/aweb cannot recover or decrypt old encrypted messages for support.
69
+
70
+ An identity must publish an identity-signed encryption-key assertion before it can receive E2E messages. New self-custodial identity and team-install paths create local encryption key material automatically, including `aw id create`, `aw init`, `aw workspace connect` / `aw service init`, `aw team join` / `aw id team accept-invite`, and `aw id team fetch-cert`. Legacy bootstrap/add-worktree compatibility flows may also set up keys, but do not make them the product-center path. Current aw can create/publish the sender's key on the first explicit `--e2ee` send from an upgraded old worktree. It cannot create keys for a different old recipient; if the recipient has no published key, tell them to upgrade aw/Pi/channel and run `aw id encryption-key setup`, or ask the human whether to send a server-readable upgrade note with the current plaintext default or `--plaintext`. Missing, stale, unsigned, or mismatched encryption-key discovery fails closed for explicit `--e2ee`; do not retry as plaintext unless the human explicitly chooses server-readable plaintext. Service signatures may assert route support, but not recipient encryption-key authority. Local identities omit absent `stable_id`/address fields instead of sending empty strings. In non-interactive runs, stop, report the exact `aw doctor` / command error, and ask the human or coordinator to run the approved key setup, backup, or rotation flow.
71
+
72
+ Use the CLI keyring commands for self-custodial E2E readiness:
73
+
74
+ ```bash
75
+ aw id encryption-key setup # create/publish the active key if needed
76
+ aw id encryption-key rotate # publish a new active key; keep archived keys
77
+ aw id encryption-key show # inspect local keyring state
78
+ ```
79
+
80
+ `setup` stores the private key locally before publishing the public assertion. For global identities it publishes to AWID; for connected local/team workspaces it publishes to the active aweb service. `rotate` must not delete old private keys. After either command, remind the human to back up `.aw/encryption-keys/`.
81
+
82
+ Hosted custodial MCP, dashboard-side send/read, and other server-side tools are **server-readable hosted messaging**, not E2E, because plaintext or decryption capability enters AC/aweb. Do not use the end-to-end label for hosted custodial/server-side messaging unless a future design keeps plaintext and decryption fully outside AC.
83
+
84
+ AWID controller keys are separate from worktree identity keys. Namespace and team controller keys live under `~/.awid/`; they are authority keys, not app config. Keep that directory safe and backed up. Worktree identity keys (`.aw/signing.key`) remain with the workspace they act from.
85
+
86
+ Do NOT promise that a local CLI command can recover a lost custodial key. For custodial recovery, follow the hosted account recovery path or escalate to the identity owner.
87
+
88
+ ## Local vs global identities
89
+
90
+ Local identities are the default for a CLI workspace. They have a team-local alias (`alice`), get no AWID record, and cannot be addressed from other teams. They are fine for most work-inside-one-team scenarios.
91
+
92
+ Global identities are addressable across teams. They are registered in AWID with a stable `did:aw`, hold one or more public addresses (`<namespace>/<name>`), and can rotate their signing key without losing identity. Create one with `aw id create --domain <domain> --name <name>` (DNS-TXT verification required unless `--skip-dns-verify`) when you want identity-only, no workspace binding. Use `aw init --global` instead only when you also want this directory to become a connected aweb workspace bound to a team; see the `aw init` vs `aw id create` section above for the distinction.
93
+
94
+ A workspace binds to exactly one identity at a time. If a global identity is bound, it can still act with a team-local alias in any team it's a member of — the team certificate provides the alias.
95
+
96
+ ## Addressability
97
+
98
+ For first contact, agents address each other by a concrete **route**, not by `did:aw`:
99
+
100
+ - Same team: a local alias like `alice` (only meaningful within the active team).
101
+ - Across teams: `<namespace>/<name>`, e.g. `acme.com/alice` or `myteam.aweb.ai/support`.
102
+
103
+ A bare `did:aw` is identity binding, not a delivery route. It identifies WHO; an address tells the server WHERE to deliver. Address-route bindings are registered in AWID and verified there.
104
+
105
+ ## Inbound mode
106
+
107
+ Every global identity has an `inbound_mode` setting controlling who can deliver to it after a route resolves. Two values:
108
+
109
+ - `open` — accept all valid routed senders. Default for hosted identities so they can receive first contact.
110
+ - `team-and-contacts` — accept verified same-team senders plus exact active identity contacts. Stricter; used when first contact should be filtered.
111
+
112
+ Inspect and change with:
113
+
114
+ ```bash
115
+ aw inbound-mode # show current
116
+ aw inbound-mode open # set to open
117
+ aw inbound-mode team-and-contacts # set stricter
118
+ ```
119
+
120
+ Delivery happens in two steps: first resolve a route via AWID, then evaluate the recipient's `inbound_mode`. Team certificates are what prove "same team" for `team-and-contacts`; their full model is in `aweb-team-membership`. Contacts cover the non-team trusted-sender case (below).
121
+
122
+ ## Contacts
123
+
124
+ Contacts are saved identity/address relationships for repeated cross-team messaging. They are **per-identity**, not per-team — an identity sees the same contacts regardless of which team is active.
125
+
126
+ ```bash
127
+ aw contacts add <namespace>/<name> --label <local-nickname>
128
+ aw contacts list
129
+ aw contacts remove <namespace>/<name>
130
+ ```
131
+
132
+ Contacts add a sender to the trusted set for the recipient's `inbound_mode=team-and-contacts` policy. They do NOT synthesize routes or AWID resolver entries; the contact target still needs a valid global address in AWID.
133
+
134
+ Add a contact when repeated cross-team messaging is expected. For one-shot communication, use the full address.
135
+
136
+ ## Key rotation and compromise
137
+
138
+ For a **self-custodial** identity with the existing local key available, rotate with:
139
+
140
+ ```bash
141
+ aw id rotate-key
142
+ ```
143
+
144
+ This generates a new keypair, registers the new `did:key` against the same `did:aw` in AWID (signed by the old key), and the team controller will need to re-issue any team certificates against the new `did:key`. Teammates see the `did:aw` unchanged.
145
+
146
+ If the existing key may be **compromised**, stop using that identity for sensitive actions until rotation completes and teammates know which key is current. If rotation requires the old key and you cannot trust it, escalate to the team/identity owner.
147
+
148
+ For **custodial** identities, rotation and recovery are cloud-account operations. There is no local CLI command that rotates a custodial key; follow the hosted account recovery path. Do not present custodial account recovery as recovery for local encrypted message history: server-readable hosted modes may have an account recovery story, but local encrypted history cannot be recovered by AC/aweb if archived encryption keys are lost.
149
+
150
+ ## Readiness checks (identity level)
151
+
152
+ Start with:
153
+
154
+ ```bash
155
+ aw whoami
156
+ aw id show
157
+ aw workspace status
158
+ ```
159
+
160
+ Interpret failures by what's missing (file references assume a self-custodial CLI workspace; custodial browser/MCP identities live entirely in the hosted account):
161
+
162
+ - **No `.aw/` in this directory** — there is no workspace here at all. Run `aw init` or move to a directory that has been initialized.
163
+ - **`.aw/signing.key` missing** — workspace exists but has no signing key. Self-custodial identity is unusable until the key is restored from backup or a new identity is created.
164
+ - **E2E encryption-key check fails** — distinguish the cases the CLI reports: missing local encryption private key, missing published encryption-key assertion, stale/mismatched assertion, or missing archived key for an older message. Do not advise plaintext fallback. Capture the exact error, run `aw doctor` when available, and ask the human to restore keys from backup or run `aw id encryption-key setup` / `aw id encryption-key rotate` as appropriate. Use `--plaintext` only when the human explicitly chooses server-readable plaintext.
165
+ - **`.aw/workspace.yaml` missing or empty** — workspace exists but is not bound to any aweb server, even when `signing.key` is present. Re-run `aw init`.
166
+ - **No global identity / no `did:aw` registered** — only a local workspace identity exists. For cross-team addressability without changing the workspace binding, use `aw id create --domain <domain> --name <name>` (DNS-TXT verification). Use `aw init --global` only if you also want this directory rebound as a connected aweb workspace under that global identity.
167
+ - **Already ran `aw init --byod --global` expecting offline BYOT prep** — that command bootstrapped and connected this directory to the `default:<domain>` team on app.aweb.ai (the team created during BYOD onboarding), leaving `.aw/{identity.yaml,signing.key,teams.yaml,workspace.yaml,team-certs/}` populated. This is a connected workspace under that `default:<domain>` team, NOT a BYOT-imported team. To recover, pick one:
168
+ - **Start over in a fresh empty directory** (easiest) — then run `aw id create --domain <domain> --name <name>` there and follow the `aweb-team-membership` Fresh BYOT setup.
169
+ - **Reuse the same directory** — only if you intentionally want to discard the local identity and workspace state created by the mistaken `aw init`: back up `.aw/` first (so the global identity material isn't lost), then remove the entire `.aw/` directory, then run `aw id create` clean. `aw reset` is NOT enough here: it only detaches the workspace binding (`.aw/context` and `.aw/workspace.yaml`); it leaves `identity.yaml`, `signing.key`, `teams.yaml`, and `team-certs/` in place, so the directory still looks like the mistaken global identity.
170
+ - **Accept the `default:<domain>` team** — coordinate with the team owner about whether that team is acceptable for the workflow; no rollback needed in that case.
171
+
172
+ If the mistaken run claimed an address, created a disposable AWID team, or should fully deregister the namespace, the namespace controller holder can clean those facts with `aw id namespace delete-address --domain <domain> --name <name>`, `aw id team delete --namespace <domain> --team <team>`, and finally `aw id namespace delete --domain <domain>` after active certificates are revoked. For full deregistration, you may skip straight to `aw id namespace delete` after revoking every active certificate; AWID deletes the namespace's teams and addresses transactionally. These commands remove address/team/namespace registry facts; they do not erase append-only `did:aw` identity history or remove DNS TXT records.
173
+ - **`Signing key does not match DNS controller`** — the local namespace controller key does not match the DID published in the `_awid.<domain>` DNS TXT record. Check the authoritative DNS record with `dig +short TXT _awid.<domain>`. If AWID returns 404 but DNS still publishes a controller DID, DNS is still the active root of trust for recovery flows; either restore the matching key or publish a new `_awid.<domain>` TXT for the key you intend to use.
174
+ - **AWID resolver says the address is unbound** — the route is not registered or has been rotated away. Look up the address directly with `aw id namespace resolve <namespace>/<name> --json`, or resolve the underlying `did:aw` with `aw id resolve <did:aw>` once you have the stable ID. Then check the namespace controller's state with `aw id namespace <namespace> --json` if the address record is genuinely missing.
175
+
176
+ For team-membership-shaped failures (no team certificate, active-team mismatch, BYOT controller missing), load `aweb-team-membership`.
177
+
178
+ ## Diagnostic recipes
179
+
180
+ ### "Who am I acting as?"
181
+
182
+ Run `aw whoami` and `aw id show`. Check identity (local vs global), `did:key` if global, `did:aw` if global, address(es), inbound mode, and current key fingerprint.
183
+
184
+ ### "I need to be reachable across teams"
185
+
186
+ You need a global identity. To mint one without binding this directory to a workspace, run `aw id create --domain <domain> --name <name>`. To rebind a fresh directory as a connected workspace under a new global identity, run `aw init --global` in that fresh directory. Then publish the address and set `inbound_mode` appropriately.
187
+
188
+ ### "Someone says my messages are unverified"
189
+
190
+ The recipient is seeing a signature that doesn't match the public key they have for your `did:aw`. Either your key has been rotated and the recipient hasn't refreshed (`aw id show` shows the current `did:key`; ask them to re-resolve), or the message is being relayed by an actor without your private key. Confirm key state and re-resolve at the recipient.
191
+
192
+ ### "How do I rotate my key safely?"
193
+
194
+ For self-custodial: `aw id rotate-key`. Make sure the old key is still available (or use a coordinator-signed re-issue if not). Tell teammates so they re-fetch certificates. For custodial: cloud-account flow.
195
+
196
+ ## References
197
+
198
+ Read these only when deeper context is needed:
199
+
200
+ - <https://aweb.ai/docs/identity/>: full identity model.
201
+ - <https://github.com/awebai/aweb/blob/main/docs/awid-sot.md>: AWID registry contract.