@passioncode-ai/fabric-agent-adapter 0.79.1 → 0.81.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.
Files changed (120) hide show
  1. package/CHANGELOG.md +213 -0
  2. package/README.md +13 -2
  3. package/SECURITY.md +23 -8
  4. package/bin/fabric-agent-adapter.js +50 -5
  5. package/package.json +1 -1
  6. package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
  7. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +6 -4
  8. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/agents-database.md +4 -4
  9. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/dashboard-links.md +12 -4
  10. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/provider-entry.md +1 -1
  11. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/source-and-instance.md +44 -7
  12. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +107 -2
  13. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/check_dashboard_link.py +26 -6
  14. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_provider.py +9 -1
  15. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_secrets.py +24 -5
  16. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_check.py +57 -76
  17. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_restart.py +56 -0
  18. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_tree.py +912 -0
  19. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/new_agent.py +308 -0
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +8 -4
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/dashboard-only/README.md +67 -0
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/dashboard-only/dashboard_service.py +252 -0
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/dashboard-only/install.mjs +168 -0
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/dashboard-only/install.py +179 -0
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/key-delivery-door/README.md +57 -0
  26. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/key-delivery-door/door.mjs +181 -0
  27. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/key-delivery-door/door.py +237 -0
  28. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +1 -1
  29. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/agents-database.md +4 -4
  30. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +4 -2
  31. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md +12 -4
  32. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +7 -3
  33. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/estate-record.md +12 -1
  34. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +54 -3
  35. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +6 -3
  36. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +33 -12
  37. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/migrating-a-service.md +1 -0
  38. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/package.md +10 -0
  39. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +25 -7
  40. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/remote-placement.md +44 -3
  41. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_layout.mjs +21 -0
  42. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_link.py +26 -6
  43. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +24 -33
  44. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_channel_agent.py +12 -6
  45. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +136 -3
  46. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-session.mjs +3 -0
  47. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-slots.mjs +1 -0
  48. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-context.mjs +37 -5
  49. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +118 -3
  50. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-holds.mjs +266 -0
  51. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +72 -7
  52. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-hub.mjs +16 -2
  53. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-load.mjs +344 -0
  54. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +98 -1
  55. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-peer-owner.mjs +7 -3
  56. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -1
  57. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-secrets.mjs +10 -3
  58. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +11 -0
  59. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +114 -20
  60. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-usage.mjs +8 -1
  61. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_session.py +3 -2
  62. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_slots.py +2 -0
  63. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_connections.py +97 -3
  64. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_context.py +50 -8
  65. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +120 -3
  66. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_holds.py +316 -0
  67. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +40 -3
  68. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_hub.py +15 -2
  69. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +2 -2
  70. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_load.py +358 -0
  71. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package.py +103 -1
  72. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_peer_owner.py +28 -13
  73. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -1
  74. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_secrets.py +24 -5
  75. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +23 -0
  76. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +110 -9
  77. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_usage.py +12 -1
  78. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +469 -29
  79. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +4 -1
  80. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +18 -6
  81. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/agent-templates.md +44 -0
  82. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/agents-database.md +4 -4
  83. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/communication-agent-template.md +19 -328
  84. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/dashboard-links.md +12 -4
  85. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/models-and-providers.md +1 -1
  86. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/new-agent.md +42 -0
  87. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/resilience-and-autonomy.md +7 -1
  88. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/source-and-instance.md +44 -7
  89. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/where-agents-run.md +28 -0
  90. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/working-rules.md +54 -0
  91. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/access.schema.json +50 -0
  92. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/connections.schema.json +23 -0
  93. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/data-rooms.schema.json +74 -0
  94. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/manifest.schema.json +170 -0
  95. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/template-header.schema.json +25 -0
  96. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/check_dashboard_link.py +26 -6
  97. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/template_check.py +491 -0
  98. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/CHANGELOG.md +7 -0
  99. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/TEMPLATE.md +347 -0
  100. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/access.json +24 -0
  101. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/assembly.md +15 -0
  102. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/checks/acceptance.md +17 -0
  103. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/connections.json +29 -0
  104. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/data-rooms.json +9 -0
  105. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/manifest.json +32 -0
  106. package/plugins/fabric-agent-adapter/skills/observing-products/SKILL.md +1 -1
  107. package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +21 -21
  108. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/agents-database.md +4 -4
  109. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/cleanup.md +30 -0
  110. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/on-demand-session.md +2 -1
  111. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/project-board.md +3 -2
  112. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/remote-sessions.md +75 -0
  113. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/session-hooks.md +28 -13
  114. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/task-context.md +58 -0
  115. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/waits.md +36 -0
  116. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session.py +14 -0
  117. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py +143 -36
  118. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +136 -15
  119. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mcp.py +78 -3
  120. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_paths.py +9 -2
@@ -0,0 +1,42 @@
1
+ # One command for a new agent project
2
+
3
+ `new` creates an agent project with the contract built in, from the kit's template (FAA-270, North Star G21). It runs
4
+ after the intake grill (step 0) has named the agent's id, its profile and whether it runs as a service; the grill's
5
+ other answers still go into the project by hand.
6
+
7
+ ```bash
8
+ npx @passioncode-ai/fabric-agent-adapter new <folder> --id <agent-id> [--profile mcp|a2a|local-runner] [--service]
9
+ python3 <plugin-dir>/skills/adapting-projects-to-fabric/scripts/new_agent.py <folder> --id <agent-id> [...]
10
+ ```
11
+
12
+ Both run the same script (the npm command runs it under the first Python 3.9 or later on PATH). Optional flags:
13
+ `--capability <domain.action>` (default `<id>.run`), `--effect <class>` (default `none`: declare money, deletion or
14
+ publication now), `--force`, `--json`.
15
+
16
+ ## What it writes
17
+
18
+ | Path | What |
19
+ |---|---|
20
+ | `fabric-agent.json`, `fabric-contract.lock.json`, `fabric/` | the provider bundle `adapt_project.py scaffold` writes, pinned to the contract; every value it invents is a sentinel `adapt_project.py check` names |
21
+ | `fabric.source.json` | the source manifest (DEC-0149): `include` names the project's source, default deny; the slots are the publisher's URI behind `provider.createdBy` (`PUBLISHER_URI`), the placement record (`PLACEMENT_RECORD`) and, for a service, its supervisor label and port (`SUPERVISOR_LABEL`, `SERVICE_PORT`), never a value ([the source and the instance](source-and-instance.md)) |
22
+ | `src/placement.py`, `tests/test_placement.py` | the placement guard ([where agents run](where-agents-run.md), *Its own machine*): placed on another machine, it refuses to start; no record, it starts; a record it cannot read, it starts degraded; the three cases are its tests |
23
+ | `config/placement.example.json` | Project Observatory's placement record (`observatory-placement/1`) on neutral values: the shape the guard reads |
24
+ | `README.md`, `LICENSE`, `.gitignore` | the layout and the slots by name; all rights reserved until the owner names the terms; the instance kept out of Git |
25
+ | `service/` (with `--service`) | the service kit's sample (`service.py`, a `fabric-service/0.1` service) and the kit modules it imports, copied by `fabric_kit.py install` so `fabric_kit.py status` checks them later |
26
+ | `fabric/new-agent.json` | the arguments it was made with, so a repeat is recognised |
27
+
28
+ ## Rules
29
+
30
+ - **Idempotent.** A repeat with the same arguments in a folder this command made changes nothing and answers the same
31
+ line with `"repeated": true`.
32
+ - **Never over someone's files.** A folder holding anything else is refused (exit 1) unless `--force`, which writes the
33
+ planned files over it and leaves every other file as it is.
34
+ - **The last stdout line is JSON:** `{"folder", "id", "profile", "service", "created", "repeated"}`; `--json` prints
35
+ only it. Exit 0 made or already made, 1 refused (the reason on stderr), 2 usage.
36
+ - **Done means checked.** The new project passes `fabric_source_check.py check <folder>` under its own manifest and its
37
+ own tests; a service passes `check_service.py` against its sample once it is served and registered
38
+ (`python3 service/service.py serve --id <agent-id> --port <port> --data-dir <data>`, then `register` with
39
+ `--repository`). Then the sentinels are replaced, the grill's answers written in, and the agent built.
40
+
41
+ What it does not do yet: infer the agent from a sentence (`new "<sentence>"`) and run its evals (`test`). Both stay with
42
+ FAA-26, blocked on Fabric's `fabric.agent.create`.
@@ -216,6 +216,12 @@ leaves a held task still. The working-with-fabric skill's Step 5 carries it; Fab
216
216
  transaction, and log a transaction held long with the step that held it. Every blocking network
217
217
  wait is interruptible from outside, with its deadline on the socket, not between frames.
218
218
 
219
+ 13. **A routine fails its run when writing its result fails.** A scheduled or background routine (a digest, a
220
+ snapshot, a measurement, a sync) whose result file, row, report or board message cannot be written (a full disk,
221
+ a refused write, a lost connection, a schema the store refuses) exits non-zero and records the failure by its
222
+ code; it never logs success over a result nobody can read, and the next run sees the gap instead of yesterday's
223
+ value standing as today's. Its tests: a test makes the write fail and sees the run fail (FAA-294).
224
+
219
225
  ## Secrets and confinement
220
226
 
221
227
  1. **A secret never enters an environment, argv, URL or log a child can read.** The agent's own
@@ -268,7 +274,7 @@ Before the first release, answer each with a file and a test: where a limit paus
268
274
  `accept` each model call has; which vendors its fallback and checker use; where the attempt ledger
269
275
  and idempotency keys live; what happens to an unknown outcome; which waits are durable; who owns the
270
276
  run lock; what the next start sweeps; how a cancel reaches paid inner work; which outputs are
271
- capped; how a secret reaches a child; which test was seen failing for each fix; and, for an agent
277
+ capped; which routine fails its run when its result cannot be written; how a secret reaches a child; which test was seen failing for each fix; and, for an agent
272
278
  that writes text for people, where its prompt says no em dash and which test fails on U+2014 in its
273
279
  output; and where each piece of work's retro is written (its lessons through `observatory_lesson`, or the agent's own retrospective
274
280
  file without Project Observatory; its insight/1 lines in `insights/`, practices.md *Reliability*) and which test shows it.
@@ -7,13 +7,15 @@ first commit, so that its owner can hand the source over later without rewriting
7
7
  by itself: handing over, a new remote, a push or a change of visibility stays the owner's act, each time (a personal
8
8
  agent stays private until its owner says so about that act).
9
9
 
10
- The format of a source manifest, export and import is the contract's to decide (CT-194). What follows does not depend
11
- on it.
10
+ The format of a source manifest, export and import is the contract's: DEC-0149 (`fabric-source/1`, its `source.md`) at
11
+ the pin. The kit lays down `fabric.source.json` ([the source manifest](#the-source-manifest)), and the check reads the
12
+ source under it.
12
13
 
13
14
  ## Contents
14
15
 
15
16
  - [The layout](#the-layout)
16
17
  - [The data home and its kind](#the-data-home-and-its-kind)
18
+ - [The source manifest](#the-source-manifest)
17
19
  - [The check](#the-check)
18
20
 
19
21
  ## The layout
@@ -42,11 +44,11 @@ on it.
42
44
  - **Fixtures on neutral ids.** A test that needs a home folder, an owner or an account uses `example`, `example-agent`,
43
45
  `owner@example.com` or a one-letter home, and a credential-shaped test value says it is synthetic
44
46
  (`sk-test-not-a-key`) or is assembled at run time.
45
- - **Two names stay in the source until the contract decides (CT-194).** A service's supervisor label is the agent's
46
- own name, reverse-DNS on the publisher's domain (`com.example.example-agent`), and `AGENTS.md` names it (LC-09):
47
- never the owner's account or name. A provider's `createdBy` names the publisher; until one is chosen it
48
- keeps the scaffold's sentinel, and a person's name or account is never written there. The adapter moves both when the
49
- contract decides how an instance renames them (FAA-188 part 2).
47
+ - **Two names are slots, never values (DEC-0149, FAA-188 part 2).** A service's supervisor label is the agent's own
48
+ name, reverse-DNS on the publisher's domain (`com.example.example-agent`), and `AGENTS.md` names it (LC-09): never the
49
+ owner's account or name; the label an installation runs under is its `SUPERVISOR_LABEL` slot, with its port in
50
+ `SERVICE_PORT`. A provider's `createdBy` names the publisher; the source keeps the scaffold's sentinel, and the
51
+ publisher's URI is the installation's `PUBLISHER_URI` slot, so a person's name or account is never written there.
50
52
 
51
53
  ## The data home and its kind
52
54
 
@@ -69,6 +71,41 @@ on it.
69
71
  configuration and dependency folders `--every-file` reads too), each exit 0, with the owner's list or its absence recorded, until the contract's export (CT-194)
70
72
  replaces it.
71
73
 
74
+ ## The source manifest
75
+
76
+ `fabric.source.json` at the source's root says what is source and which slots an installation fills, never a value
77
+ (DEC-0149, `fabric-source/1`):
78
+
79
+ | Member | What |
80
+ |---|---|
81
+ | `include` | the source, default deny: a file outside every entry is not source; an entry ending in `/` is a folder, no globs |
82
+ | `exclude` | holes in `include`, read in any letter case and Unicode form (a file an entry names only in another spelling is left out, and the check says `excluded-by-fold`) |
83
+ | `binaries` | the binary files that are source (an icon, a font); another binary blocks |
84
+ | `unchecked` | source paths that travel unread, each with its reason (synthetic test vectors, a licence naming a holder on the owner's list) |
85
+ | `publicAddresses` | the e-mail addresses the source may carry (a support address); another one warns |
86
+ | `slots` | what an installation fills, by name: `secret` (a key), `config` (a setting: a repository URL, a folder, the supervisor label, the publisher's identity), `store` (a data store, with its path in the data folder), `endpoint` (the operator's infrastructure by role) |
87
+
88
+ - **Laying it down.** A new agent gets it from `new_agent.py` (creating-fabric-agents' `references/new-agent.md`); an
89
+ existing project from `adapt_project.py source <project-root>` (adapting-projects-to-fabric's scripts), which proposes `include` from the
90
+ project's top-level entries (what Git would commit, instance data by its name left out) and names the kit's slots
91
+ (`PUBLISHER_URI` where a provider manifest is there, `PLACEMENT_RECORD`, and with `--service` `SUPERVISOR_LABEL` and
92
+ `SERVICE_PORT`); `--secret NAME:PURPOSE` and `--store NAME:PATH:PURPOSE` add the agent's own. `--dry-run` prints the
93
+ proposal and writes nothing; an existing manifest is the owner's and is replaced only with `--force`. The author then
94
+ narrows `include` to what is source.
95
+ - **The check under it.** When the folder it checks holds `fabric.source.json`, `fabric_source_check.py check` reads
96
+ the source the manifest names and reports the contract's kinds (`fabric_source_tree.py`, held to the contract's
97
+ vectors): blocking `home-path`, `credential`, `binary`, `nested-repository`, `instance-string`, `missing`,
98
+ `no-include` and the manifest's own findings (FAC-SEM-156, FAC-SEM-157); warnings `email`, `link-outside`,
99
+ `no-license`, `unused-exclude`, `excluded-by-fold`, each by path, line and column (UTF-16 units), never by the text
100
+ found. Exit 1 on a blocking finding, 0 when only warnings remain and every source file was read, 2 when one was not.
101
+ `.fabric-source-ignore` and `--exclude` are not read there: `exclude` and `unchecked` say it. A declared home
102
+ (`home: <name>`) is still found in every source file.
103
+ - **Packing it.** `pack` (building-fabric-services' `references/package.md`) writes the package's `secrets[]` from the secret slots and `state[]` from the store slots' paths, and refuses a
104
+ package whose members differ (FAC-SEM-160); an empty `state[]` is a copy packed without state, and stays so. A
105
+ hand-written `secrets[]` naming a secret the manifest has no slot for is refused by name, never dropped.
106
+ - **Handing it over** stays the owner's act, each time, on their word for that act (the contract's `source.md`,
107
+ Handing over).
108
+
72
109
  ## The check
73
110
 
74
111
  `fabric_source_check.py check` reads the files the source would carry (what Git would commit: tracked files and
@@ -17,6 +17,7 @@ The normative rules are the Fabric Agent Contract's, at the commit this plugin p
17
17
  - [Sharing an agent into an organization](#sharing-an-agent-into-an-organization)
18
18
  - [Running while the laptop is closed](#running-while-the-laptop-is-closed)
19
19
  - [Uptime: A or B](#uptime-a-or-b)
20
+ - [Its own machine: placement, keys and port](#its-own-machine-placement-keys-and-port)
20
21
  - [Selling an agent](#selling-an-agent)
21
22
  - [The checklist](#the-checklist)
22
23
 
@@ -115,6 +116,31 @@ Every new agent is given an uptime category on its first day, and the README nam
115
116
  A B agent that gains a capability that must answer around the clock becomes A for that capability; record the change
116
117
  and move only that capability to the cloud.
117
118
 
119
+ ## Its own machine: placement, keys and port
120
+
121
+ An agent that may run on more than one machine of the estate (a laptop and a personal cloud, an old and a new
122
+ computer during a move) runs on exactly one at a time, and each copy reads only its own machine's keys.
123
+
124
+ - **Placement.** At start, before it polls, schedules or listens, the agent reads Project Observatory's placement
125
+ record, `${XDG_DATA_HOME:-~/.local/share}/project-observatory/placement.json` (schema `observatory-placement/1`;
126
+ Observatory's `observatory/engine/machine_identity.py`). An entry of its `elsewhere` list whose `serviceId` is the
127
+ agent's `id.instance`, or whose `label` is its launchd label or systemd unit, and whose `placedOn` is not the file's
128
+ `machine`, says the agent runs on another machine: it refuses to start, writes one log line and reports
129
+ `degraded` with the reason `placed-elsewhere` and the machine id where it can, and starts nothing that acts. With
130
+ no file (Observatory absent, nothing ever moved) it starts. A file it cannot read, or one of another schema, does
131
+ not stop it: it starts and reports `degraded` with `placement-unreadable`, since a guard that cannot read refuses
132
+ nothing the estate recorded. `full machine-move leave LABEL --to MACHINE` writes the entry and stops the job here;
133
+ `full machine-move cutover LABEL` removes it on the machine the job moves to. A supervisor that restarts on exit
134
+ (`KeepAlive`, `Restart=always`) restarts a refused copy under its throttle: stopping the job here is `leave`'s, and
135
+ the refusal guards a copy started anyway (a restore, a start by hand). Its tests start one copy placed elsewhere and see it refuse, and one with no file and one with a
136
+ malformed file and see them start.
137
+ - **Keys.** Each copy reads its credentials only from its own vault, the vault of the OS account and machine it
138
+ runs on (`use_secret.py run` there), never copied from another machine's or account's vault, a backup or a file a
139
+ move carried. A key the new machine needs is issued anew there through the provider's door, or asked of the
140
+ person once, and the old machine's key is revoked when the copy there stops.
141
+ - **Port.** Until the contract's port-claim decision (DEC-0160) lands, the kit refuses a port another OS account
142
+ already listens on (FAA-225); the port recorded per account and its claim file follow DEC-0160.
143
+
118
144
  ## Selling an agent
119
145
 
120
146
  - **A paid agent** runs in PassionCode's cloud inside its developer's organization (`org:<developer>`); each customer
@@ -133,6 +159,8 @@ and move only that capability to the cloud.
133
159
  - Which capabilities need the person's machine, and what do they answer when it is off?
134
160
  - On a computer with more than one counted OS account, or under a member's virtual machine: a port recorded per
135
161
  account, the listener's owner checked before a token is sent, no token-free loopback door (DEC-0154).
162
+ - On a machine of its own: it starts only on the machine `placement.json` names (or with no entry for it), and reads
163
+ keys from that machine's own vault.
136
164
  - Which uptime category is it, A (a cloud host from the first release) or B (local only)? The README names it.
137
165
  - Who pays for each call (which grant, which key)? The person's personal key never pays for an organization.
138
166
  - If it joins machines or applies the estate record: tokens from stdin or a 0600 file only, revisions verified with
@@ -0,0 +1,54 @@
1
+ # Working rules a new agent carries from its first commit
2
+
3
+ Three rules the operator set for every agent (board message `bfc0e14e`, 2026-11-12: FAA-299, FAA-300, FAA-301). A
4
+ new agent's template (its `AGENTS.md`, its system prompt, its session start) states each one, and a test pins each
5
+ one's key sentence, so a copy of the agent cannot lose them. The working-with-fabric skill states the same rules for a
6
+ coding session; this page is what the agent you build says about itself.
7
+
8
+ ## Contents
9
+
10
+ - [The context of a task](#the-context-of-a-task)
11
+ - [A wait is not a stop](#a-wait-is-not-a-stop)
12
+ - [Clean up after yourself](#clean-up-after-yourself)
13
+ - [The checklist](#the-checklist)
14
+
15
+ ## The context of a task
16
+
17
+ Follows the contract's CT-292 draft (rules TC-1 to TC-6, `docs/evidence/plans/2026-11-12-ct292-task-context.md` at
18
+ `753c5093`) until its DEC lands (the contract's slice of 2026-11-21).
19
+
20
+ An agent that can reach resources of more than one context (`personal`, `org:<orgId>`, contract DEC-0082) **settles
21
+ the task's context at session start, before its first act on them**, from: the operator's words; the board request's
22
+ Project; the folder's Project by folder attribution (DEC-0089) and its organization; the grant's context (DEC-0082);
23
+ the place. The context is settled when every source that names one names the same one.
24
+
25
+ When none names it, or they disagree, **the agent asks the operator once, naming the candidates and what each would
26
+ do; it never guesses, never picks a "safest" one and never splits the task across contexts.** With no person in the
27
+ session the question goes through `fabric_question_ask` (the candidates as `options`). This is the one exception to
28
+ the template's "do not ask, do it" rule for the operator's word (FAA-207, CT-220). The answer is recorded in the
29
+ handoff as `{context, by: "operator", at, source}`, so the next agent does not ask again. The question and the answer
30
+ never go into either organization's board thread.
31
+
32
+ The template's session start reads the five sources before any tool that acts across contexts; an agent that reaches
33
+ only one context asks nothing and says which one in its report.
34
+
35
+ ## A wait is not a stop
36
+
37
+ The agent finishes a unit of work and takes the next in the same turn (the board's next open task, a request addressed
38
+ to it, the handoff's next task). **Every wait has its condition, owner, next action and watcher, or an honest "no
39
+ watcher".** `fabric_heartbeat` carries `waitingOn` (`question`, `grant` or `continuation`, with its id) or a one-line
40
+ `note` while it waits. **A turn ends with one line per open wait, never with "shall I continue?"**
41
+
42
+ ## Clean up after yourself
43
+
44
+ After a merge the agent **removes its own worktrees and branches locally and on origin, then runs `git fetch
45
+ --prune`**. A branch with commits found nowhere else is archived under `refs/archive/<date>/` before it is deleted. It
46
+ removes build output and dependency folders in its abandoned or merged copies and stops its own processes. **It never
47
+ touches another session's worktree, a `locked` one, or a Git-tracked file: `git ls-files -- <dir>` must print nothing
48
+ before a folder is removed.**
49
+
50
+ ## The checklist
51
+
52
+ - [ ] The template states the context rule, its one question and where the answer is recorded; a test pins it.
53
+ - [ ] The template states "a wait is not a stop" with the four parts of a wait and the turn's last lines; a test pins it.
54
+ - [ ] The template states the cleanup rule with its `git ls-files` check; a test pins it.
@@ -0,0 +1,50 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/passioncode-ai/fabric-agent-adapter/schemas/template/access.schema.json",
4
+ "title": "access.json of an agent template: per access level, what it does without asking, what needs approval, what escalates",
5
+ "type": "object",
6
+ "required": ["levels", "never"],
7
+ "additionalProperties": false,
8
+ "patternProperties": {"^x-[a-z0-9-]+$": {}},
9
+ "properties": {
10
+ "levels": {
11
+ "type": "object",
12
+ "required": ["owner", "administrator", "project_architect", "member"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "owner": {"$ref": "#/$defs/owner"},
16
+ "administrator": {"$ref": "#/$defs/level"},
17
+ "project_architect": {"$ref": "#/$defs/level"},
18
+ "member": {"$ref": "#/$defs/level"}
19
+ }
20
+ },
21
+ "never": {"type": "array", "items": {"type": "string", "minLength": 1}, "description": "what the agent never does at any level"},
22
+ "rule": {"type": "string", "minLength": 1},
23
+ "notes": {"type": "string"}
24
+ },
25
+ "$defs": {
26
+ "acts": {"type": "array", "items": {"type": "string", "minLength": 1}},
27
+ "level": {
28
+ "type": "object",
29
+ "required": ["without_asking", "with_approval", "escalates"],
30
+ "additionalProperties": false,
31
+ "properties": {
32
+ "without_asking": {"$ref": "#/$defs/acts"},
33
+ "with_approval": {"$ref": "#/$defs/acts"},
34
+ "escalates": {"$ref": "#/$defs/acts"},
35
+ "notes": {"type": "string"}
36
+ }
37
+ },
38
+ "owner": {
39
+ "type": "object",
40
+ "required": ["without_asking", "with_approval", "escalates"],
41
+ "additionalProperties": false,
42
+ "properties": {
43
+ "without_asking": {"$ref": "#/$defs/acts"},
44
+ "with_approval": {"$ref": "#/$defs/acts"},
45
+ "escalates": {"type": "array", "maxItems": 0, "description": "nobody stands above the owner"},
46
+ "notes": {"type": "string"}
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/passioncode-ai/fabric-agent-adapter/schemas/template/connections.schema.json",
4
+ "title": "connections.json of an agent template: the source classes it reads and writes, each with its connector and grant",
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "required": ["source_class", "connector", "grant", "required", "direction"],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "source_class": {"type": "string", "minLength": 1, "description": "a class of source (a tracker, a chat, a store), never one installation"},
12
+ "connector": {"type": "string", "minLength": 1},
13
+ "grant": {"type": "string", "minLength": 1, "description": "the grant or scope it needs, by name; never a value"},
14
+ "required": {"type": "boolean"},
15
+ "when": {"type": "string", "minLength": 1, "description": "the condition under which an optional connection is needed, or under which a required one applies"},
16
+ "direction": {"enum": ["read", "write", "read-write", "call"]},
17
+ "scope": {"type": "string", "minLength": 1, "description": "what the direction covers, in words (\"draft pull requests only\")"},
18
+ "spends": {"type": "boolean", "description": "true when a call through it costs money (rule A6)"},
19
+ "variants": {"type": "array", "items": {"type": "string"}, "minItems": 1, "uniqueItems": true},
20
+ "notes": {"type": "string"}
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/passioncode-ai/fabric-agent-adapter/schemas/template/data-rooms.schema.json",
4
+ "title": "data-rooms.json of an agent template: the rooms and blocks it reads or writes ([] when none)",
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "required": [
9
+ "room",
10
+ "blocks",
11
+ "access"
12
+ ],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "room": {
16
+ "type": "string",
17
+ "minLength": 1
18
+ },
19
+ "blocks": {
20
+ "type": "array",
21
+ "items": {
22
+ "type": "string",
23
+ "minLength": 1
24
+ },
25
+ "minItems": 1,
26
+ "uniqueItems": true
27
+ },
28
+ "access": {
29
+ "enum": [
30
+ "read",
31
+ "write",
32
+ "read-write"
33
+ ]
34
+ },
35
+ "scope": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "description": "what the access covers, in words (\"its own block\", \"aggregate cells only\")"
39
+ },
40
+ "classes": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "string",
44
+ "minLength": 1
45
+ },
46
+ "minItems": 1,
47
+ "uniqueItems": true,
48
+ "description": "the data classes it may touch in the block"
49
+ },
50
+ "level": {
51
+ "type": "string",
52
+ "minLength": 1,
53
+ "description": "whose level bounds the read (\"the asker's level\")"
54
+ },
55
+ "required": {
56
+ "type": "boolean"
57
+ },
58
+ "variants": {
59
+ "type": "array",
60
+ "items": {
61
+ "type": "string"
62
+ },
63
+ "minItems": 1,
64
+ "uniqueItems": true
65
+ },
66
+ "use": {
67
+ "type": "string"
68
+ },
69
+ "notes": {
70
+ "type": "string"
71
+ }
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,170 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/passioncode-ai/fabric-agent-adapter/schemas/template/manifest.schema.json",
4
+ "title": "manifest.json of an agent template: placement, contract, doors, dashboard, base model per task, budget",
5
+ "description": "placement, doors, models, dashboard and budget sit at the top level, or in every entry of `variants` when the variants differ. Their inner shape is the template's own in schema 1.",
6
+ "type": "object",
7
+ "required": [
8
+ "template",
9
+ "version",
10
+ "contract"
11
+ ],
12
+ "additionalProperties": false,
13
+ "patternProperties": {
14
+ "^x-[a-z0-9-]+$": {}
15
+ },
16
+ "properties": {
17
+ "template": {
18
+ "type": "string",
19
+ "pattern": "^[a-z][a-z0-9-]{1,63}$",
20
+ "description": "equals TEMPLATE.md's template.id"
21
+ },
22
+ "version": {
23
+ "type": "string",
24
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$",
25
+ "description": "equals TEMPLATE.md's template.version"
26
+ },
27
+ "contract": {
28
+ "description": "one protocol the template was checked against, or a map of them by role",
29
+ "oneOf": [
30
+ {
31
+ "$ref": "#/$defs/protocol"
32
+ },
33
+ {
34
+ "type": "object",
35
+ "minProperties": 1,
36
+ "additionalProperties": {
37
+ "$ref": "#/$defs/protocol"
38
+ }
39
+ }
40
+ ]
41
+ },
42
+ "placement": {
43
+ "type": [
44
+ "object",
45
+ "string"
46
+ ]
47
+ },
48
+ "doors": {
49
+ "type": [
50
+ "object",
51
+ "array"
52
+ ]
53
+ },
54
+ "models": {
55
+ "type": [
56
+ "object",
57
+ "array"
58
+ ]
59
+ },
60
+ "dashboard": {
61
+ "type": [
62
+ "object",
63
+ "string"
64
+ ]
65
+ },
66
+ "budget": {
67
+ "type": [
68
+ "object",
69
+ "string"
70
+ ]
71
+ },
72
+ "schedules": {
73
+ "type": [
74
+ "array",
75
+ "object",
76
+ "string"
77
+ ]
78
+ },
79
+ "limits": {
80
+ "type": "object"
81
+ },
82
+ "events": {
83
+ "type": "array"
84
+ },
85
+ "variants": {
86
+ "type": "object",
87
+ "minProperties": 1,
88
+ "additionalProperties": {
89
+ "type": "object",
90
+ "properties": {
91
+ "placement": {
92
+ "type": [
93
+ "object",
94
+ "string"
95
+ ]
96
+ },
97
+ "doors": {
98
+ "type": [
99
+ "object",
100
+ "array"
101
+ ]
102
+ },
103
+ "models": {
104
+ "type": [
105
+ "object",
106
+ "array"
107
+ ]
108
+ },
109
+ "dashboard": {
110
+ "type": [
111
+ "object",
112
+ "string"
113
+ ]
114
+ },
115
+ "budget": {
116
+ "type": [
117
+ "object",
118
+ "string"
119
+ ]
120
+ }
121
+ }
122
+ }
123
+ },
124
+ "notes": {
125
+ "type": "string"
126
+ }
127
+ },
128
+ "$defs": {
129
+ "protocol": {
130
+ "type": "object",
131
+ "required": [
132
+ "name",
133
+ "home",
134
+ "checked_against"
135
+ ],
136
+ "additionalProperties": false,
137
+ "properties": {
138
+ "name": {
139
+ "type": "string",
140
+ "minLength": 1
141
+ },
142
+ "home": {
143
+ "type": "string",
144
+ "minLength": 1
145
+ },
146
+ "checked_against": {
147
+ "type": "string",
148
+ "minLength": 1,
149
+ "description": "the version or date checked against: \"checked against\", never \"requires\""
150
+ },
151
+ "extensions": {
152
+ "type": "array",
153
+ "items": {
154
+ "type": "string",
155
+ "minLength": 1
156
+ },
157
+ "uniqueItems": true,
158
+ "description": "the protocol's extensions the template uses, by name"
159
+ },
160
+ "applies_to": {
161
+ "type": "string",
162
+ "minLength": 1
163
+ },
164
+ "notes": {
165
+ "type": "string"
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/passioncode-ai/fabric-agent-adapter/schemas/template/template-header.schema.json",
4
+ "title": "The `template:` header of an agent template's TEMPLATE.md (fabric-workspace S2, decision W0-Q8)",
5
+ "type": "object",
6
+ "required": ["template"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "template": {
10
+ "type": "object",
11
+ "required": ["id", "name", "version", "family", "checked", "readiness", "variants"],
12
+ "additionalProperties": false,
13
+ "properties": {
14
+ "id": {"type": "string", "pattern": "^[a-z][a-z0-9-]{1,63}$", "description": "equals the folder's name"},
15
+ "name": {"type": "string", "minLength": 1, "maxLength": 120},
16
+ "version": {"type": "string", "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"},
17
+ "family": {"type": "string", "pattern": "^[a-z]+(-[a-z]+)*$"},
18
+ "checked": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},
19
+ "readiness": {"enum": ["draft", "validated", "proven"]},
20
+ "sources": {"type": "integer", "minimum": 0},
21
+ "variants": {"type": "array", "items": {"type": "string", "pattern": "^[a-z][a-z0-9-]{0,63}$"}, "uniqueItems": true}
22
+ }
23
+ }
24
+ }
25
+ }