@passioncode-ai/fabric-agent-adapter 0.80.2 → 0.82.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 (92) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/README.md +18 -5
  3. package/SECURITY.md +25 -8
  4. package/bin/fabric-agent-adapter.js +24 -1
  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/dashboard-links.md +16 -3
  9. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/source-and-instance.md +44 -7
  10. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +116 -4
  11. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/check_dashboard_link.py +33 -3
  12. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_secrets.py +257 -10
  13. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_check.py +57 -77
  14. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_restart.py +56 -0
  15. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_source_tree.py +899 -0
  16. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/new_agent.py +308 -0
  17. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +7 -4
  18. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-button.js +23 -5
  19. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +1 -1
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +2 -2
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json +9 -4
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +1 -1
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +4 -2
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +15 -2
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md +16 -3
  26. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +5 -2
  27. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +28 -0
  28. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +4 -3
  29. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +47 -10
  30. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/migrating-a-service.md +1 -0
  31. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/package.md +10 -0
  32. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +31 -8
  33. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_layout.mjs +21 -0
  34. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_link.py +33 -3
  35. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +19 -28
  36. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_channel_agent.py +9 -6
  37. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +146 -3
  38. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-connections.mjs +3 -2
  39. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +2 -0
  40. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +79 -2
  41. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-holds.mjs +269 -0
  42. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +64 -5
  43. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-hub.mjs +16 -7
  44. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-lock.mjs +73 -3
  45. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +98 -1
  46. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-peer-owner.mjs +89 -22
  47. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -1
  48. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-secrets.mjs +39 -6
  49. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +8 -0
  50. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +76 -11
  51. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_connections.py +8 -153
  52. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +86 -2
  53. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_holds.py +324 -0
  54. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +34 -3
  55. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_hub.py +35 -17
  56. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_lock.py +77 -4
  57. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package.py +103 -1
  58. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_peer_owner.py +156 -133
  59. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -1
  60. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_secrets.py +257 -10
  61. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +6 -0
  62. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +64 -3
  63. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +246 -24
  64. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +16 -6
  65. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/agent-templates.md +44 -0
  66. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/communication-agent-template.md +19 -328
  67. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/dashboard-links.md +16 -3
  68. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/models-and-providers.md +1 -1
  69. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/new-agent.md +42 -0
  70. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/source-and-instance.md +44 -7
  71. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/access.schema.json +50 -0
  72. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/connections.schema.json +23 -0
  73. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/data-rooms.schema.json +74 -0
  74. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/manifest.schema.json +170 -0
  75. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/schemas/template/template-header.schema.json +25 -0
  76. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/check_dashboard_link.py +33 -3
  77. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/template_check.py +491 -0
  78. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/CHANGELOG.md +7 -0
  79. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/TEMPLATE.md +347 -0
  80. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/access.json +24 -0
  81. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/assembly.md +15 -0
  82. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/checks/acceptance.md +17 -0
  83. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/connections.json +29 -0
  84. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/data-rooms.json +9 -0
  85. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/templates/communication-agent/manifest.json +32 -0
  86. package/plugins/fabric-agent-adapter/skills/observing-products/SKILL.md +1 -1
  87. package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +2 -2
  88. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/on-demand-session.md +16 -8
  89. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/project-board.md +46 -31
  90. package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/session-hooks.md +1 -1
  91. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py +18 -16
  92. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +23 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,162 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.82.0 (2026-11-12)
4
+
5
+ Wave 4 of the backlog sweep of 2026-11-12. The contract pin stays at `93e7db16` (`v0.1.0+2026-11-08.1`). Kit modules
6
+ change: `fabric_secrets`, `fabric_connections`, `fabric_peer_owner` (`1.2.0+kit.6`), `fabric_descriptor`,
7
+ `fabric_holds`, `fabric_hub`, `fabric_lock`, the facade `fabric_service`, `fabric-delegation.mjs`, and their Node twins;
8
+ dashboard kit 1.1.7.
9
+
10
+ ### Changed
11
+
12
+ - **working-with-fabric answers a board request as contract DEC-0152 SA-6 says** (FAA-311): a session reads the
13
+ capability's slot in `com.status` first; at an `active` slot, or an enroll refused `fenced`, it leaves the request to
14
+ that holder, sends nothing and asks no one; it declines only at a slot `absent` at generation 0, and asks the operator
15
+ with `fabric_question_ask` after any refusal that is not retryable. A session without the slot does no work on a
16
+ request and gives it no state. The exit contract, the preamble, `SKILL.md` and the references say so, the exit
17
+ contract within Hermes' 4000 characters (3996).
18
+ - **The peer owner reads DEC-0155's restricted table** (FAA-312): a `netstat` that fails or exits non-zero, a macOS
19
+ table with no row of another uid (sysctl) or process (netstat), and one without the reader's own connection read
20
+ `table-restricted` (RT-1); Linux and Windows keep `no-row`. Under a restricted table a listener is this account's only
21
+ on exactly `127.0.0.1` (RT-4). The launchd vouch takes only a listen on exactly `127.0.0.1` (RT-3), never the IPv4
22
+ wildcard or `::1`, and nothing from a set-uid reader: the kit's wildcard departure ends. `PEER_OWNER_VERSION` is
23
+ `1.2.0+kit.6`.
24
+ - **The kit's hub locator answers a pid another OS account holds as the session hooks do** (FAA-304, after FAA-254):
25
+ `pid_alive` / `pidAlive` give None / null and `locate_hub` / `locateHub` refuse with `not-a-hub`, retryable, "not
26
+ verified", never `not-running`.
27
+ - **`fabric_secrets.secret_url` refuses a URL whose host or port `new URL` refuses** (FAA-309), as `secretUrl` does:
28
+ the WHATWG host reading and the IDNA tables of FAA-98 move into `fabric_secrets` (`fabric_connections` imports them;
29
+ new `url_refused`). `repository_credential` still reads a repository's parameters whatever its host.
30
+ - **One-pass JWT reading** (FAA-313): `has_jwt` / `jwt_spans` (Node `hasJwt` / `jwtSpans`), the same answers in linear
31
+ time; `secret_value`, `secret_argument`, the channel-agent check and `fabric_source_tree` use it.
32
+ - **The holds twins agree on whitespace** (FAA-316): both squash a `statusMessage` with one ECMAScript class, so
33
+ U+001C, U+0085 and U+FEFF read the same; four vectors in `test/fixtures/holds/waiting-vectors.json`.
34
+ - **The probe's `lifecycle.one-copy` finds a LaunchDaemon's leftover LaunchAgent** (FAA-317) in its `UserName`'s
35
+ `gui/<uid>` first, then in the probe's own; `in_launch_daemons` is `fabric_supervisors._in_daemons`, imported.
36
+ - **Dashboard kit 1.1.7** (FAA-314): `fabric-button.js` reads credentials with DEC-0151's `SECRET_VALUE`, held to the
37
+ contract's `secretValue` and `credentialName` vectors.
38
+
39
+ ### Fixed
40
+
41
+ - **A copy holding the instance lock stops when its lock file is replaced** (FAA-303, the 0.79.0 seam reading). On
42
+ macOS `flock` and `O_EXLOCK` lock an inode, so a data folder swapped under a running copy let a second copy lock the
43
+ new file and start. `hold_single_instance` / `holdSingleInstance` now start `InstanceLock.watch` /
44
+ `InstanceLock#watch` there: every `LOCK_WATCH_SECONDS` (2 s) it compares the locked inode with the file at the path,
45
+ and once the path names another file the copy exits 75 with one sentence naming the path (`lost_lock_message` /
46
+ `lostLockMessage`; `on_lost` / `onLost` replaces that reaction). The two copies overlap for at most one interval.
47
+ Linux and Windows keep their path-keyed name and are unchanged.
48
+ - **Tests that failed under load** (FAA-308): the linear-time tests for `raw_values` and the minified JSON line read the
49
+ thread's CPU time, not the wall clock (kept on Windows), so a load near 110 no longer fails them, while a quadratic
50
+ implementation still does; the board sample's probe test lets `well-known.fast`, which times the machine, go either
51
+ way, as `test_probe_interop` does.
52
+ - A flaky test drew a SAS signature without a digit about once in 1500 runs, a shape the long-run rule excludes by its
53
+ definition; it now draws one in the rule's shape.
54
+
55
+ - **What the 0.82.0 seam reading found, fixed before the release**: Python's credential readers
56
+ (`fabric_secrets.url_refused` and its copy, `fabric_connections._whatwg_parts`, `check_service_channel_agent.url_parts`)
57
+ refuse a URL whose empty host is followed by `:`, with or without a port, as `new URL` does (`foo://:/?token=...`;
58
+ four shared vectors in both suites). `adapt_project`'s LC-21 gates read a stored URL's credential without the host
59
+ check, so a password in a manifest or `plugin.json` URL is found whatever its host. Every other reader of the JWT rule
60
+ reads it in one pass too (`fabric_source_check`, `fabric_connections` and its Node twin, the three
61
+ `check_dashboard_link.py` copies, `fabric-button.js`). Python `pid_alive` on Windows (`fabric_hub`,
62
+ `fabric_session_env`) answers None when OpenProcess is refused with access denied, as Node's EPERM does. The README
63
+ states the preamble's request rule; the exit contract's closing checkpoint names its `status` again (done if
64
+ completed, blocked if failed_known); the hub and HTTP docstrings say a missing row on macOS is `table-restricted`.
65
+ New rows FAA-320 to FAA-323.
66
+
67
+ ### Added
68
+
69
+ - **`fabric_peer_owner.py listener <port> [--json]`** and **`fabric-peer-owner.mjs listener <port>`** print the
70
+ listener's kind (FAA-315): the route for the dashboard link gate's `listener_owner`, named in the three
71
+ `dashboard-links.md`.
72
+
73
+ ### Documented
74
+
75
+ - On a host with a restricted socket table the dashboard layout probe measures nothing: every rule `NOT_RUN`, exit 3
76
+ (FAA-318). It does not vouch by the service's pid, which DEC-0155 RT-3 reserves for the caller that started it.
77
+ - FAA-292's decision: RT-2 through libproc waits for an L0 module of its own, as `fabric_peer_owner.py` is at the
78
+ 1000-line cap (`docs/evidence/specs/2026-11-12-faa-292-libproc-decision.md`); the row stays open.
79
+ - `fabric-delegation.mjs` carries the `<https>` legend; `HTTPS_LEGEND_PENDING` in `test/validate.py` is empty (FAA-306).
80
+
81
+ ## 0.81.0 (2026-11-12)
82
+
83
+ Wave 3 of the backlog sweep of 2026-11-12. **The contract pin moves to `93e7db16` (`v0.1.0+2026-11-08.1`)**: DEC-0149
84
+ (`fabric-source/1`), CT-254 (HA-2's Linux source, the hybrid the kit already read), DEC-0151, DEC-0152, DEC-0155.
85
+ Bundles pinned at `18f8d487` stay valid (FAA-258; impact map `docs/evidence/specs/2026-11-12-faa-258-repin-93e7db16-impact-map.md`).
86
+ New kit modules: `fabric_holds` and `fabric-holds.mjs`. Kit modules change: `fabric_secrets`, `fabric_protocols`,
87
+ `fabric_peer_owner` (`1.2.0+kit.5`), `fabric_package`, `fabric_descriptor`, `fabric_http`, `fabric_supervisors`, the
88
+ facade `fabric_service`, and their Node twins.
89
+
90
+ ### Added
91
+
92
+ - **`npx @passioncode-ai/fabric-agent-adapter new <folder> --id <agent-id> [--profile ...] [--service]`** (North Star G21,
93
+ FAA-270), and `new_agent.py` behind it: one command creates an agent project with the contract built in: the bundle
94
+ pinned at the contract, `fabric.source.json`, a placement guard reading Observatory's `observatory-placement/1` record
95
+ with its tests, and with `--service` the service kit's sample (its modules copied by `fabric_kit.py install`).
96
+ Idempotent, refuses a folder holding other files without `--force`, JSON last. It needs Python 3.9 or later on the
97
+ machine. Turning a sentence into an agent (`new "<sentence>"`, `test`) stays FAA-26, waiting on Fabric's
98
+ `fabric.agent.create`.
99
+ - **`fabric.source.json` (DEC-0149, `fabric-source/1`)** (FAA-261): `fabric_source_tree.py` ports the contract's source
100
+ rules and matches all 140 of its vendored vectors; `fabric_source_check.py check` reads the source a manifest names,
101
+ by path, line and column, never the value; `adapt_project.py source` lays the manifest down with the kit's slots
102
+ (`PUBLISHER_URI` behind the `createdBy` sentinel, `PLACEMENT_RECORD`, and for a service `SUPERVISOR_LABEL` and
103
+ `SERVICE_PORT`; FAA-188's part 2); `pack` writes `secrets[]` and `state[]` from the slots, and FAC-SEM-160 refuses a
104
+ package that differs.
105
+ - **Work held by a service's own limits** (FAA-298): new kit modules `fabric_holds` and `fabric-holds.mjs` (L3). A held
106
+ job says why it waits in `statusMessage` with the contract's pause grammar (the job schema is closed); the operator gets
107
+ one push per hold, and the answer is recorded as a scoped lift that falls back when its window ends; a new probe rule
108
+ `limits.holds`.
109
+ - **Agent template folders** (FAA-265): five JSON Schemas and `template_check.py` in creating-fabric-agents; the
110
+ communication agent template moved into `templates/communication-agent/` with its manifest, connections, access, data
111
+ rooms, checks, assembly and changelog; `validate.py` checks every shipped template folder.
112
+
113
+ ### Changed
114
+
115
+ - The probe's `limits.holds` reads a service that declares limits but does not use `fabric_holds` as NOT_RUN with a
116
+ migration note, not FAIL, and counts only code files (a vendored `check_service_rules.py` and docs naming `HoldBook`
117
+ no longer pass it). `LoopbackHTTPServer` and `loopbackServer` read the socket table only for a loopback peer: a peer
118
+ at another address (a `0.0.0.0` bind) is served with no owner under `refuse` and `strict` (the 0.81.0 seam reading).
119
+ - **A kit service refuses a loopback peer of another OS account before it reads the request** (DEC-0154 HA-2 and HA-3,
120
+ FAA-227): `LoopbackHTTPServer` takes `peer_check` and Node's new `loopbackServer(httpServer, {peerCheck})` holds each
121
+ connection paused until the check passes; `refuse` (the default) closes another account's peer and serves the rest,
122
+ `strict` also refuses an owner it cannot tell, `off` reads nothing.
123
+ - `fabric_http` and `fabric-http.mjs` check plain http that reaches loopback by its connected address, `insecure=True` and
124
+ a loopback proxy included (FAA-260). The probe times the well-known answer after the owner check, fails a deeply
125
+ nested body cleanly, compares port claims as ports (`:08080` is `:8080`), names the listener on a failed connect, and
126
+ no longer stops on a well-known body that is not an object; the layout probe opens a loopback page only after its
127
+ listener is this account's (FAA-260).
128
+ - The dashboard link gate opens a raw loopback address in a browser only when `listener_owner` is `this-account` as
129
+ well as the host `not_installed` (FAA-251).
130
+ - LaunchDaemon installs and uninstalls refuse contradicting domains, leftover LaunchAgents, another label's plist and an
131
+ unparseable or binary plist, and remove a plist a failed bootstrap wrote; the probe fails a LaunchDaemon without
132
+ `UserName`, with a `~` command, or loaded in both domains (FAA-286).
133
+ - **The kit's credential detector is the contract's DEC-0151 `SECRET_VALUE`**, in both twins and the three dashboard
134
+ link checkers: a provider prefix counts only in its canonical case and after a boundary; an `sk-` key needs a digit and
135
+ an upper-case letter (16 characters or more) or a digit (32 or more), so `SK-...`, `sk-learn-...` and an `sk-` inside a
136
+ word are no longer keys. Repository names keep their own boundary-free key shapes, as DEC-0151 asks (FAA-258).
137
+ - `fabric_protocols` lists `fabric-source/1`; `fabric_peer_owner` is `1.2.0+kit.5`, one version line with Observatory's
138
+ 1.2.0, the Linux reading unchanged (FAA-258).
139
+ - Every vendored contract vector is regenerated at the new pin with the contract's own generators;
140
+ `make_load_vectors.mjs` reads the pin from the lock file. SECURITY.md, lifecycle.md and protocol.md name DEC-0155 RT-3
141
+ for the vouch; SA-6 (DEC-0152) is the accepted board rule (FAA-258).
142
+
143
+ ### Fixed
144
+
145
+ - `fabric_source_check.py` refuses a copy without `fabric_source_tree.py` with exit 2 and the file's name, not a
146
+ traceback and exit 1; `pack` (both kits) refuses by name a hand-written `secrets[]` naming a secret `fabric.source.json`
147
+ has no slot for, instead of dropping it (the 0.81.0 seam reading). The Windows job runs the loopback peer check.
148
+
149
+ ### Upgrading
150
+
151
+ - A door that gave T0 because `strict` served the peer must also check that the peer's owner is named
152
+ (`peer_owner()` / `connectionOwner`): a peer off loopback has none and is T2. A folder whose `fabric.package.json`
153
+ names secrets its `fabric.source.json` lacks fails `pack` until they are added as `secret` slots.
154
+ - A service that serves loopback HTTP keeps serving its own account's callers; pass `peer_check="strict"` to refuse an
155
+ owner the table cannot tell. A caller of the dashboard link gate passes `listener_owner`. An outside test that runs
156
+ this checkout's probe needs a readable socket table.
157
+ - A service that vendors the kit takes the changed `fabric_secrets`, `fabric_protocols` and `fabric_peer_owner` with
158
+ `fabric_kit.py install`. A string the 0.80 detector called a key may no longer be one (see Changed).
159
+
3
160
  ## 0.80.2 (2026-11-12)
4
161
 
5
162
  0.80.1 was tagged and never published: its `windows` job (run 43212508702) failed one test, so `release` and `publish`
package/README.md CHANGED
@@ -23,10 +23,12 @@ The skills are `adapting-projects-to-fabric`, `creating-fabric-agents`,
23
23
  `working-with-fabric` is for the other side: a coding agent (Claude Code, Codex, Kimi Code, Kilo, Hermes) opened in
24
24
  a terminal that works in a project through Fabric. It finds Fabric (`hub.json`, its `pid`), has the machine's
25
25
  lifecycle broker start it when it is down, registers `fabric-mcp` once with no secret, calls `fabric_whoami`
26
- first, reads the project board (`com.status`, `com.list`, `com.read_ack` only what was read), answers what waits on its
27
- Project in the same turn with its state (the result later; a request its Project's service should take stays queued; before Fabric 0.3.17 a run Fabric starts
26
+ first, reads the project board (`com.status`, `com.list`, `com.read_ack` only what was read): an announcement or
27
+ question waiting on its Project gets its state in the same turn (the result later), and a request to its Project is
28
+ read through its capability's slot in `com.status` (`active` is left to its holder and nobody is asked; otherwise
29
+ `com.enroll`, and only the slot's holder gives the request its state; before Fabric 0.3.17 a run Fabric starts
28
30
  declines a request no session can take and the asker resends, and from 0.3.17 the session's own Project is granted
29
- `board.respond` at `com.enroll`, CO-506), and asks other
31
+ `board.respond` at `com.enroll`, CO-506). It asks other
30
32
  Projects only through `com.submit`, asks who is working on what and claims its task before it starts
31
33
  (`fabric_work_list`, `fabric_work_claim`, Fabric v0.3.5 and later), links tasks to backlog rows instead of copying them, and
32
34
  releases at the end (`fabric_work_release`). `scripts/fabric_session.py status` prints where Fabric stands and one
@@ -152,7 +154,9 @@ For provider bundles the adapting skill helps an agent author:
152
154
  admission, and project binding;
153
155
  - keep the agent's source apart from its instance data, with `scripts/fabric_source_check.py check`, which reports a
154
156
  home path, a credential-shaped value or a string from the owner's list by path, line and kind and never repeats it
155
- (FAA-188).
157
+ (FAA-188); under the source manifest `fabric.source.json` (contract DEC-0149, `fabric-source/1`, which
158
+ `scripts/adapt_project.py source` proposes) it reads the source the manifest names with the contract's tree check
159
+ (FAA-261), and `pack` writes the package's `secrets[]` and `state[]` from its slots.
156
160
 
157
161
  The skill never treats generated files as admission. Fabric contract `0.1.0` does not
158
162
  yet ship the host registry/runtime needed to connect and authorize a live provider.
@@ -169,6 +173,7 @@ then restart your agents. Alone, without any account:
169
173
  npx @passioncode-ai/fabric-agent-adapter # installs every skill into the agents hub ~/.agents/skills
170
174
  npx @passioncode-ai/fabric-agent-adapter --prune-shadow # remove ~/.claude/skills copies that shadow the plugin
171
175
  npx @passioncode-ai/fabric-agent-adapter --force # update a copy already in the hub (a launcher link is never replaced)
176
+ npx @passioncode-ai/fabric-agent-adapter new ./example-agent --id example-agent [--service] # a new agent project, contract built in
172
177
  ```
173
178
 
174
179
  A copy already in the hub is left alone unless `--force` is given; with it, the new copy is built beside the old one
@@ -300,8 +305,16 @@ python3 "$SKILL_DIR/scripts/adapt_project.py" scaffold /path/to/project \
300
305
  --effect none
301
306
  python3 "$SKILL_DIR/scripts/adapt_project.py" check /path/to/project \
302
307
  --contract /path/to/fabric-agent-contract --json
308
+ python3 "$SKILL_DIR/scripts/adapt_project.py" source /path/to/project --dry-run # propose fabric.source.json
309
+ python3 "$SKILL_DIR/scripts/new_agent.py" ./example-agent --id example-agent # what `npx ... new` runs
303
310
  ```
304
311
 
312
+ `new` (FAA-270) writes a new agent project from the kit's template: the provider bundle pinned to the contract,
313
+ `fabric.source.json`, the placement guard with its tests, and with `--service` the service kit's sample; a repeat
314
+ changes nothing, a folder holding other files is refused without `--force`, and the last line is JSON
315
+ ([new-agent.md](plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/new-agent.md)). Inferring the agent
316
+ from a sentence and running its evals (`new "<sentence>"`, `test`) stay with FAA-26.
317
+
305
318
  Pack, sign and verify an agent as a `fabric-package/1` folder (contract DEC-0050, DEC-0051; nothing is written without
306
319
  `--apply`, and the key file is the person's, never made or kept here). First check the checkout, then make the clean
307
320
  copy [the package reference](plugins/fabric-agent-adapter/skills/building-fabric-services/references/package.md)
@@ -330,7 +343,7 @@ Scaffolding is non-destructive by default. It writes only the paths declared in
330
343
  The default pin for new bundles is [`fabric-contract.lock.json`](fabric-contract.lock.json):
331
344
 
332
345
  - version: `0.1.0`
333
- - commit: `18f8d48762edc5bfb1433657cbfe1c16196df1a6`
346
+ - commit: `93e7db164c7829e2783b4b7705c4113bb5201131`
334
347
 
335
348
  Every other mention of the default contract revision (this section, the skills' metadata, the
336
349
  skill card, `adapt_project.py`) must equal it; `python3 test/validate.py` fails a tree
package/SECURITY.md CHANGED
@@ -31,7 +31,7 @@ bounded and non-publishing until explicit scoped grants exist in a project bindi
31
31
  there with an explicit `domain="gui"`, not refused yet, FAA-286 item 21); the job runs as the account its `UserName`
32
32
  names. The installer accepts the job's answer only on a connection launchd's own job accepted
33
33
  (its pid from `launchctl print system/<label>`) or, where the socket table is restricted, on a port that pid listens
34
- on (`lsof -p`, the weaker vouch below, CT-261). The
34
+ on (`lsof -p`, the weaker vouch below, DEC-0155 RT-3). The
35
35
  token is readable by any process of the same user; the protocol defends against web pages
36
36
  and mistakes, not against hostile local code.
37
37
  - The kits' connectors (`fabric_http`, `fabric_openrouter` and their Node twins) reach the
@@ -48,25 +48,42 @@ bounded and non-publishing until explicit scoped grants exist in a project bindi
48
48
  restricted table, to a port that pid listens on there (the weaker vouch below): a departure from the pinned HA-2 and
49
49
  the contract's later RT-3, accepted in principle by the contract owner as DEC-0161 (proposed; the restricted-table vouch
50
50
  included) and kept as a departure until the next repin (FAA-288). They read, never change:
51
- macOS `sysctl net.inet.tcp.pcblist_n` in the process, or the programs `/usr/sbin/netstat
51
+ macOS `sysctl net.inet.tcp.pcblist_n` in the process (the TCP table in the record layout `netstat -anv` reads;
52
+ the pinned HA-2 table names `netstat -anv` and `pcblist64`, an older layout of the same table), or the programs `/usr/sbin/netstat
52
53
  -anv -p tcp` and `/bin/ps -o uid= -p <pid>` (the Node twin always); Linux
53
54
  `/proc/net/tcp` and `/proc/net/tcp6`; Windows `GetExtendedTcpTable` and the process
54
- token (Python), or `netstat -ano`, `whoami /user` and one PowerShell `GetOwnerSid` query
55
- per new connection (Node). On macOS the Python reader calibrates once per process with a
55
+ token (Python), or `netstat -ano` and one PowerShell `GetOwnerSid` query per new connection,
56
+ with `whoami /user` once a process (Node). On macOS the Python reader calibrates once per process with a
56
57
  short-lived child of its own interpreter listening on a random `127.0.0.1` port; when the
57
58
  table is restricted (macOS 27.2, FAA-267) the launchd installers also run `/usr/sbin/lsof
58
59
  -nP -a -p <pid> -i4TCP -sTCP:LISTEN -Fn` on their own job's pid. That vouch shows the job listens on the port, not that it accepted
59
- the connection (a more specific bind by root over a wildcard job would pass; contract CT-261). A LaunchDaemon's root
60
+ the connection; it counts only a listen on exactly `127.0.0.1`, as the pin's DEC-0155 RT-3 asks (since FAA-312; a wildcard
61
+ or `::1` listener is never vouched for, and a set-uid reader vouches for nothing). A LaunchDaemon's root
60
62
  installer runs that `lsof` and `ps -o uid=` on its job's pid before it accepts an answer, and reads, never changes, every other
61
63
  plist in `/Library/LaunchDaemons` (to find another holder of its label, `plutil -convert xml1` for a binary one in
62
- Node), `launchctl print system/<label>` and the `UserName`'s uid (`pwd`, or `id -u` in Node). A token-free loopback door is not yet protected against
63
- another account's process (HA-3, FAA-227). An MCP client (Claude Code, Codex) sends the
64
+ Node), `launchctl print system/<label>` and the `UserName`'s uid (`pwd`, or `id -u` in Node). The kit's loopback server reads the table once per accepted
65
+ connection and closes a peer of another account before reading it (HA-3, FAA-227); a token-free door counts as
66
+ protected only under `peer_check="strict"`, which also refuses an owner it cannot tell. An MCP client (Claude Code, Codex) sends the
64
67
  token it was registered with on every later connection without this check (the contract's
65
68
  residue "a coding agent's bearer"): when the port may have changed hands, rotate the token
66
69
  and re-run `mcp-register` (one written as `references/surfaces-and-auth.md` says checks the
67
70
  listener first; the kit ships none). On Linux `/proc` names a socket's creator and
68
71
  no pid, so a listening socket root created and handed to another account (systemd
69
- socket activation with `User=`) reads as root's: a client running as root sends to it.
72
+ socket activation with `User=`) reads as root's: a client running as root sends to it. Such a system unit's
73
+ connection reads as root's until the service accepts it and as the service's account after, so two runs of the
74
+ probe can disagree on it (0.74.0 product reading 10).
75
+ - Credential-free loopback http is checked too (FAA-260 item 16, deliberate): `fabric_http` / `fabric-http.mjs` refuse
76
+ plain http to a loopback listener of another OS account or root (another account's Ollama, a `docker-proxy`) with
77
+ kind `foreign-user` whether or not the request carries a credential, because HA-2 reads nothing such a listener
78
+ answers as the service's, and an answer from another account's process is not this account's data. A caller that
79
+ means to read such a daemon says so with its own connection. With `insecure=True` a URL not spelled as loopback
80
+ (a hosts-file name, `0.0.0.0`, `[::ffff:127.0.0.1]`) and a request through a loopback `http_proxy` are checked by the
81
+ connected peer's address, so the Authorization header never reaches another account's proxy (FAA-260 items 1, 8).
82
+ - The layout probe (`check_dashboard_layout.mjs`) reads a raw loopback page's listener from the socket table just
83
+ before its headless browser opens it, the one-time login URL included, and opens nothing on another account's,
84
+ root's or an untellable listener (FAA-260 items 2, 14); under a restricted table (DEC-0155) that is every listener,
85
+ so it measures nothing there and never vouches by a pid it did not start (FAA-318). The browser then connects on its own: a listener swapped
86
+ between the read and the browser's connect is a residue, bounded by the login code's 120 s and single use.
70
87
  - The agents database (FAA-275): creating-fabric-agents, adapting-projects-to-fabric, building-fabric-services and
71
88
  working-with-fabric may send board requests to whichever Project the board lists under an `agents-db.*` capability
72
89
  (on an organization's board, any member Project may list it), carrying only what `references/agents-database.md`
@@ -43,6 +43,11 @@ Packages (fabric-package/1):
43
43
  npx @passioncode-ai/fabric-agent-adapter verify <folder> --trust <trust.json> [--countersigned]
44
44
  check the folder and its signatures against the keys you pin
45
45
 
46
+ A new agent (FAA-270; needs Python 3.9 or later):
47
+ npx @passioncode-ai/fabric-agent-adapter new <folder> --id <agent-id> [--profile mcp|a2a|local-runner] [--service] [--force] [--json]
48
+ create an agent project with the contract built in: the provider bundle, fabric.source.json, the placement
49
+ guard and, with --service, the service kit's sample; the last line is JSON
50
+
46
51
  Claude Code (recommended):
47
52
  claude plugin marketplace add ${REPO}
48
53
  claude plugin install ${PLUGIN_ID}
@@ -257,8 +262,26 @@ function main(argv) {
257
262
  return 0;
258
263
  }
259
264
 
265
+ // `new` runs the skill's own script (adapting-projects-to-fabric/scripts/new_agent.py), one implementation for the
266
+ // skill and this CLI, under the first Python 3 found on PATH; its output and exit code pass through unchanged.
267
+ function newAgent(args) {
268
+ const { spawnSync } = require('child_process');
269
+ const script = path.join(ROOT, 'plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/new_agent.py');
270
+ const candidates = process.platform === 'win32' ? [['py', ['-3']], ['python', []], ['python3', []]] : [['python3', []], ['python', []]];
271
+ for (const [command, prefix] of candidates) {
272
+ const probe = spawnSync(command, [...prefix, '-c', 'import sys; sys.exit(0 if sys.version_info >= (3, 9) else 1)'], { stdio: 'ignore' });
273
+ if (probe.status !== 0) continue;
274
+ const run = spawnSync(command, [...prefix, script, ...args], { stdio: 'inherit' });
275
+ return run.status === null ? 1 : run.status;
276
+ }
277
+ console.error('error: `new` needs Python 3.9 or later on PATH (python3, or py -3 on Windows)');
278
+ return 2;
279
+ }
280
+
260
281
  const PACKAGE_COMMANDS = ['pack', 'sign', 'verify'];
261
- if (PACKAGE_COMMANDS.includes(process.argv[2])) {
282
+ if (process.argv[2] === 'new') {
283
+ process.exitCode = newAgent(process.argv.slice(3));
284
+ } else if (PACKAGE_COMMANDS.includes(process.argv[2])) {
262
285
  // The package commands live in the kit (fabric-package.mjs), one implementation for the skill and this CLI.
263
286
  const kit = path.join(ROOT, 'plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs');
264
287
  import(require('url').pathToFileURL(kit).href).then((m) => { process.exitCode = m.main(process.argv.slice(2)); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@passioncode-ai/fabric-agent-adapter",
3
- "version": "0.80.2",
3
+ "version": "0.82.0",
4
4
  "description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
5
5
  "scripts": {
6
6
  "test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
@@ -3,7 +3,7 @@
3
3
  "name": "fabric-agent-adapter",
4
4
  "displayName": "Fabric Agent Adapter",
5
5
  "description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks; and put an agent on a standing watch over a product (observer mode).",
6
- "version": "0.80.2",
6
+ "version": "0.82.0",
7
7
  "author": {
8
8
  "name": "PassionCode.ai",
9
9
  "url": "https://passioncode.ai/"
@@ -9,9 +9,9 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
9
9
  compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode.
10
10
  metadata:
11
11
  author: PassionCode.ai
12
- version: "0.80.2"
12
+ version: "0.82.0"
13
13
  contract-version: "0.1.0"
14
- contract-commit: "18f8d48762edc5bfb1433657cbfe1c16196df1a6"
14
+ contract-commit: "93e7db164c7829e2783b4b7705c4113bb5201131"
15
15
  ---
16
16
 
17
17
  # Adapting projects to Fabric
@@ -84,7 +84,7 @@ Use exactly:
84
84
 
85
85
  - contract version `0.1.0`;
86
86
  - repository `https://github.com/passioncode-ai/fabric-agent-contract`;
87
- - commit `18f8d48762edc5bfb1433657cbfe1c16196df1a6`.
87
+ - commit `93e7db164c7829e2783b4b7705c4113bb5201131`.
88
88
 
89
89
  This is the default for new bundles. When checking an issued legacy bundle, preserve its
90
90
  explicit supported lock and use that exact clean checkout. Never silently upgrade or
@@ -184,7 +184,9 @@ path, line and kind, never repeating a value, and changes nothing. Then move eac
184
184
  instance value into the instance configuration outside the repository, read through a named variable with a neutral
185
185
  default and a committed `*.example`; a key into the secret store, named only. Run the check again until it exits 0; it is a floor under the owner's review, not a secret scanner.
186
186
  A value already committed stays in Git history: say so; a fresh history is the owner's act (no history rewrite, no
187
- force-push).
187
+ force-push). Then lay down the source manifest, `fabric.source.json` (DEC-0149): `scripts/adapt_project.py source
188
+ <project-root> --dry-run` proposes it, the author narrows `include` and names each key and store as a slot, and the
189
+ check reads the source under it (the reference, *The source manifest*).
188
190
 
189
191
  ### 5. Make probes safe and meaningful
190
192
 
@@ -65,8 +65,8 @@ host's `open` with `fallback=never`. Never `open <url>`, `open -a Safari`,
65
65
  agent's pages. A browser only when `host_status` confirms `not_installed`, and
66
66
  a raw `http://127.0.0.1:<port>` address only after the listener on that port is
67
67
  this OS account's (DEC-0154 PL-3 and HA-2; the adapter's `building-fabric-services/scripts/fabric_peer_owner.py`: `server_end` of a connection it opens and sends nothing on; `check_service.py <id>.<instance>` prints it as `listener.owner`): a
68
- `foreign-user` listener is reported, never opened (the link gate below does not
69
- read the owner yet, FAA-251). An installed host that failed
68
+ `foreign-user` listener is reported, never opened (the link gate below takes
69
+ that owner as `listener_owner`). An installed host that failed
70
70
  to open is reported, not replaced by HTTP. Links
71
71
  carry no token or login code. Every completion and notification action passes
72
72
  the Fabric Agent Adapter's link gate before delivery: `check_dashboard_link.py`
@@ -119,7 +119,20 @@ Its trusted context is supplied by the host, not by untrusted model output:
119
119
 
120
120
  `native_link` must equal the resolved open_link, with an available host on the
121
121
  viewer's device. `browser_link` must equal http_url, with confirmed not_installed,
122
- if_absent policy and the same device. Contract DEC-0123 PL-3 also allows a browser
122
+ if_absent policy, the same device and `"listener_owner": "this-account"`: the kind
123
+ the host read for the listener on http_url's port (`fabric_peer_owner`'s
124
+ `this-account`, `another-account`, `system`, `unknown`, `none`, or
125
+ `check_service.py`'s `foreign-user`); any other, or none given, refuses the
126
+ browser (DEC-0154 PL-3, FAA-251). The host reads that kind right before it opens
127
+ the page with the adapter's
128
+ `python3 building-fabric-services/scripts/fabric_peer_owner.py listener <port>`
129
+ (or `node building-fabric-services/scripts/fabric-peer-owner.mjs listener <port>`),
130
+ which prints it on one line (`--json` prints the whole owner) and sends nothing
131
+ to the port (FAA-315). Where the socket table is restricted (macOS 27.2 for an
132
+ ad-hoc-signed Python or Node, DEC-0155 RT-4) only this account's listener on
133
+ exactly `127.0.0.1` reads `this-account`; a wildcard or `::1` bind reads
134
+ `unknown` (`table-restricted`), and the browser is refused. The native link does not take it: Fabric
135
+ Dashboards checks its own listener. Contract DEC-0123 PL-3 also allows a browser
123
136
  on `unsupported` (a system the host does not ship for); the gate treats
124
137
  `unsupported` as no fallback, by the operator's rule that a browser opens only on a
125
138
  confirmed `not_installed`, and macOS never reports it (FAA-137). `remote_open` instead contains `device_id`,
@@ -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