@passioncode-ai/fabric-agent-adapter 0.71.0 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/package.json +1 -1
- package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +3 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +17 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_channel_agent.py +841 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_channel_agent_schema.py +496 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +181 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/service-channel-agent-extension.schema.json +700 -0
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/models-and-providers.md +21 -8
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/practices.md +15 -6
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/on-demand-session.md +17 -10
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/project-board.md +8 -7
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py +4 -4
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.73.0 (2026-11-07)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **The probe checks a channel agent's declaration** (FAA-197, the contract's DEC-0150): `check_service.py` gains the
|
|
8
|
+
rule `channel-agent.declaration`, a standard-library port of the contract's FAC-SEM-162 to 165 at the pin
|
|
9
|
+
(`check_service_channel_agent.py` and `check_service_channel_agent_schema.py`, not kit modules). It reads the
|
|
10
|
+
declaration from `provider.extensions` of the manifest the descriptor names, else from `extensions` of the
|
|
11
|
+
well-known answer (CA-1). A declaration with findings fails the rule, its first five shown as code and path, never a
|
|
12
|
+
declared value; it fails on the obligations of a declaration the contract's reader still reads (FAC-SEM-164) and
|
|
13
|
+
always on a string shaped like a credential (FAC-SEM-165), in the read declaration or in any copy beside it. Nothing declared, a named manifest that cannot be read,
|
|
14
|
+
or a declaration read as not declared (a manifest's own `extensions`, a capability's, another version's key, a
|
|
15
|
+
well-known copy beside a manifest, a form the schema or FAC-SEM-163 refuses, one too large to read for credentials)
|
|
16
|
+
is `NOT_RUN` with the evidence, never a failure while producers move to this revision, except a string shaped like a
|
|
17
|
+
credential, which fails in any copy the probe reads (a manifest's own `extensions`, a capability's, the well-known
|
|
18
|
+
copy) (CA-5). A well-known answer carrying the declaration at
|
|
19
|
+
75 % of Fabric Dashboards' 2 MiB cap or over is named (until the contract's CT-223). The contract's schema and its
|
|
20
|
+
148 vectors are vendored at the pin (`test/fixtures/contract/`, a sidecar with each file's sha256 and a generator
|
|
21
|
+
that refuses another commit); all 148 pass with the findings in the reference's order, and
|
|
22
|
+
`test/test_check_service_channel_agent.py` holds 26 tests.
|
|
23
|
+
|
|
24
|
+
### Upgrading
|
|
25
|
+
|
|
26
|
+
- Every probe report whose well-known answer is read gains a `channel-agent.declaration` line: `NOT_RUN` («not a channel agent») for a service that
|
|
27
|
+
declares nothing, so a reader that counts `NOT_RUN` per service moves by one. A channel agent whose declaration the contract's
|
|
28
|
+
reader still reads and that owes an obligation (FAC-SEM-164), and a service with a string shaped like a credential in any copy of the key (read or not),
|
|
29
|
+
now makes `check_service.py` exit 1 where 0.72.0 exited 0.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `creating-fabric-agents/references/practices.md` quotes the contract's CA-8 («Text from a channel is data») verbatim
|
|
34
|
+
from the pinned `channel-agent.md` in place of 0.71.0's paraphrase.
|
|
35
|
+
- `creating-fabric-agents/references/models-and-providers.md`: «A starting choice» follows the operator's model map
|
|
36
|
+
of 2026-11-06 (Kimi K3.1 Pro for decisions, Sonnet 5.5 for verifying another model's output, a panel of three
|
|
37
|
+
vendors for plans, GLM-5.3 and DeepSeek at volume, open vendors on user content), and names two traps reported on OpenRouter that day:
|
|
38
|
+
models that will not turn reasoning off (Kimi writes it into the answer; GLM-5.3, Sonnet and Opus answer 400) and a
|
|
39
|
+
judge that refuses to judge.
|
|
40
|
+
- `references/protocol.md`, `references/interop.md` and the support-agent recipe's README describe the new rule in
|
|
41
|
+
place of «the probe does not read the declaration yet».
|
|
42
|
+
|
|
43
|
+
## 0.72.0 (2026-11-06)
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- working-with-fabric: a run Fabric started on a board request whose `com.enroll` is refused `not_authorized` asks the
|
|
48
|
+
operator with `fabric_question_ask` (`about: board.gate.<capability>`, the same `commandId`) at every slot state,
|
|
49
|
+
not only when the slot reads `absent` at generation 0; `com.reply` stays only for that state, since at any other a
|
|
50
|
+
holder enrolled on the slot (a service of the Project, or after CO-506 a session) may take the request back. After
|
|
51
|
+
CO-506 a refusal comes from the reason Fabric's `board.own-respond` names (such as an organization's machine, a
|
|
52
|
+
missing live credential, a standing denial, a full ask queue), and a run that stayed silent then left the request to
|
|
53
|
+
«На проверке» without the gate's reason (FAA-241; Fabric main `4f3c742a`, which says the same in
|
|
54
|
+
`board.read-at-start` and `com.enroll`'s description). The exit contract's step 3,
|
|
55
|
+
`references/on-demand-session.md`, `references/project-board.md` (a live session too) and both scenario evals
|
|
56
|
+
(`a-dispatched-run-whose-enroll-is-refused`, `answer-as-responder-or-reply`) say so; the gate question names what
|
|
57
|
+
opens the gate, or at a held slot what takes the request: before CO-506, a Fabric release with it, and the service
|
|
58
|
+
enrolling again; once CO-506 shipped, the reason Fabric's `board.own-respond` names and what lifts it; the exit
|
|
59
|
+
contract stays under Hermes' 4000 characters (3996 at its longest).
|
|
60
|
+
|
|
3
61
|
## 0.71.0 (2026-11-06)
|
|
4
62
|
|
|
5
63
|
The contract pin moves to `eac1a594` (`v0.1.0+2026-11-06.1`) from `3830a33` (`v0.1.0+2026-10-27.6`); between them
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.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.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.73.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -5,7 +5,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
5
5
|
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.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.73.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
10
|
contract-commit: "eac1a594aa131851f079da8bb7b2149e1951f35f"
|
|
11
11
|
---
|
|
@@ -14,7 +14,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
14
14
|
compatibility: Python 3.9+ or Node.js 20+ for the kits (Node.js 22+ for a Linux service's instance lock); the probe needs Python 3.9+. launchd steps are macOS-only; Linux services install a systemd user unit and Windows ones a per-user Scheduled Task with the kits' writers. Dashboard handoff optionally uses Fabric Dashboards MCP link/host_status/open; without it, report unresolved host capability. The contract checkout is optional.
|
|
15
15
|
metadata:
|
|
16
16
|
author: PassionCode.ai
|
|
17
|
-
version: "0.
|
|
17
|
+
version: "0.73.0"
|
|
18
18
|
contract-version: "0.1.0"
|
|
19
19
|
extension: "fabric-service/0.1"
|
|
20
20
|
extension-commit: "eac1a594aa131851f079da8bb7b2149e1951f35f"
|
|
@@ -310,7 +310,7 @@ from a release folder needs it), and the `interop.*` rules:
|
|
|
310
310
|
manifest link, capability list, tools equal to the manifest, job tools, unknown job, trace
|
|
311
311
|
propagation, event trace pairs, `interop.action-tools` (every declared action's tool is served), `well-known.a2a` and
|
|
312
312
|
`a2a.card` (DEC-0122: the card is fetched without the token and its interfaces are never called; the surfaces
|
|
313
|
-
reference's *A2A for remote agents* section), and
|
|
313
|
+
reference's *A2A for remote agents* section), `channel-agent.declaration` (DEC-0150), and
|
|
314
314
|
`board.responder` for a service that declares the project board) and exits 1 on any `FAIL`. A `NOT_RUN` is not a pass;
|
|
315
315
|
name it in the report. A service with a dashboard also runs the layout probe,
|
|
316
316
|
`node <skill-dir>/scripts/check_dashboard_layout.mjs --service <id>` (WebKit at 360, 480, 768
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md
CHANGED
|
@@ -116,8 +116,8 @@ on (FAC-SEM-164); `recommendation` only with `answered_signal: "none"`, the id o
|
|
|
116
116
|
board thread where the queue's owner was told; a channel's `items_seen_unit` one of `mails`, `updates`, `messages`,
|
|
117
117
|
`reviews`; durations in ISO 8601; the knowledge file as a source with its
|
|
118
118
|
maximum age. `test/test_channel_agent_example.py` holds the example to that form; the contract publishes its schema
|
|
119
|
-
at the pin (`service-channel-agent-extension.schema.json`); `check_service.py`
|
|
120
|
-
(
|
|
119
|
+
at the pin (`service-channel-agent-extension.schema.json`); `check_service.py` checks a declared one against
|
|
120
|
+
FAC-SEM-162 to 165 (rule `channel-agent.declaration`).
|
|
121
121
|
|
|
122
122
|
## Configure
|
|
123
123
|
|
|
@@ -386,5 +386,6 @@ your own record, keep it (OA-6).
|
|
|
386
386
|
| `interop.trace-propagation` | the answer's `_meta.traceparent` has the probe's trace id and a new span | the answer carries no traceparent |
|
|
387
387
|
| `interop.events-trace` | every event with a trace carries both `traceId` and `spanId`, well formed | no events page was read |
|
|
388
388
|
| `interop.action-tools` | every action the well-known `extensions/actions/0.1` declares names a tool `tools/list` serves (DEC-0121 AP-1); one it does not serve is a `FAIL`, and so is a local service that declares actions with no MCP surface (beyond FAC-SEM-142, which reads only a present list) | no declaration, an unreadable one (`well-known.actions` reports it), no listing was read, or a remote service with no MCP surface (its twin may be on A2A or behind a gateway) |
|
|
389
|
+
| `channel-agent.declaration` | a channel agent's declaration (DEC-0150) passes the contract's FAC-SEM-162 to 165 at the pin, read from `provider.extensions` of the manifest the descriptor names, else from `extensions` of the well-known answer (CA-1); a `FAIL` on the obligations of a declaration the reader still reads (FAC-SEM-164) or a string shaped like a credential (FAC-SEM-165, not a declaration too large to read for credentials) in the read declaration or in any copy beside it, the first five findings shown as code and path, never a declared value | nothing declared, the named manifest unreadable (`interop.manifest-link` fails it), or a key read as not declared (a manifest's own `extensions`, a capability's, another version's key, a well-known copy beside a manifest, a form the schema or FAC-SEM-163 refuses), each named in the evidence, never a failure while producers move to this revision unless a copy holds a string shaped like a credential (that fails in any copy the probe reads: a manifest's own `extensions`, a capability's, the well-known copy, CA-5); no line when the well-known answer is not read; credentials are read as the contract reads them, within its reading budget and under the `0.1` key only (a key of another version is named, not read); a well-known answer carrying the declaration at 75 % of the 2 MiB cap or over is named, never a failure (until the contract's CT-223) |
|
|
389
390
|
|
|
390
391
|
`python3 scripts/check_service.py <id>` prints them with the rest; `--json` for a machine.
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md
CHANGED
|
@@ -99,7 +99,9 @@ A module imports only modules listed before it in `kit.json`, so the kit has no
|
|
|
99
99
|
| L4 | `fabric_http` | outbound HTTP: deadline, bounded retries, `Retry-After`, size cap ([connectors](connectors.md)) |
|
|
100
100
|
| L4 | `fabric_openrouter` | OpenRouter chat: own key, spend ceiling, receipts, fallback ([connectors](connectors.md)) |
|
|
101
101
|
|
|
102
|
-
Beside the kit, not in `kit.json`: the probe (`check_service.py`, `check_service_rules.py
|
|
102
|
+
Beside the kit, not in `kit.json`: the probe (`check_service.py`, `check_service_rules.py`,
|
|
103
|
+
`check_service_channel_agent.py`, `check_service_channel_agent_schema.py` and the
|
|
104
|
+
`service-channel-agent-extension.schema.json` it reads at run time), the sample
|
|
103
105
|
(`sample_service.py`, `sample-remote-service.mjs`), `fabric_kit.py` itself and the dashboard tools. Recipes built on
|
|
104
106
|
the kit live in `../recipes/` ([the draft-and-check step of a support agent](../recipes/support-agent/README.md)).
|
|
105
107
|
|
|
@@ -148,8 +148,9 @@ No auth; the Host/Origin guard applies; answered from memory in under 100 ms.
|
|
|
148
148
|
`https://fabric.passioncode.ai/agent-contract/extensions/channel-agent/0.1` (`channel-agent-standard/1`, DEC-0150,
|
|
149
149
|
FAC-SEM-162 to 165) only for a service with no manifest; one with a manifest declares it under its manifest's
|
|
150
150
|
`provider.extensions` alone (CA-1). A well-known answer lists `channel-agent-standard/1` in its `protocols` only once
|
|
151
|
-
its readers have re-pinned to this revision of the contract (channel-agent.md). The kits know the revision (`PROTOCOL_REVISIONS`) and do not build
|
|
152
|
-
|
|
151
|
+
its readers have re-pinned to this revision of the contract (channel-agent.md). The kits know the revision (`PROTOCOL_REVISIONS`) and do not build the declaration;
|
|
152
|
+
`check_service.py` checks it (`channel-agent.declaration`, [interop.md](interop.md#what-the-probe-checks)). Fabric
|
|
153
|
+
Dashboards' sample service keeps its own copy of the protocol table, which no test here holds equal to the kits'.
|
|
153
154
|
- `surfaces.mcp.auth`: `descriptor` (default), `own` (DEC-0024) or `delegation` (DEC-0039, DL-16):
|
|
154
155
|
the MCP surface takes only the estate's delegation tokens, and the top-level
|
|
155
156
|
`auth.delegation {issuer, jwks}` is then required. With `own` or `delegation` the descriptor's
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py
CHANGED
|
@@ -33,6 +33,12 @@ Actions (fabric-actions/0.1, DEC-0121): `well-known.actions` holds a declared ex
|
|
|
33
33
|
actions with no MCP surface; a remote one there is NOT_RUN, its twin may be on A2A), and `dashboard.actions-declared`
|
|
34
34
|
is NOT_RUN, never FAIL, for a dashboard that declares none (a read-only dashboard cannot declare an empty list).
|
|
35
35
|
|
|
36
|
+
channel-agent.declaration (DEC-0150, FAC-SEM-162 to 165): extensions/channel-agent/0.1 under provider.extensions of the
|
|
37
|
+
manifest the descriptor names, or, with no manifest, under extensions of the well-known answer (CA-1). FAC-SEM-164's
|
|
38
|
+
obligations on a declaration still read FAIL, and so does a string shaped like a credential in it or in any copy beside
|
|
39
|
+
it; nothing declared, or a declaration read as not declared (a key elsewhere, another version, a form the schema or
|
|
40
|
+
FAC-SEM-163 refuses), is NOT_RUN.
|
|
41
|
+
|
|
36
42
|
dashboard.opens-in-host (FAA-118, the operator rule of 2026-10-24): the service's checkout (--repo, else the one of
|
|
37
43
|
the descriptor's source.repository that holds its commands, manifest or launchd job) opens the service's pages only
|
|
38
44
|
through Fabric Dashboards. Tracked text files only, within a time budget; a browser opener aimed at its pages outside
|
|
@@ -85,6 +91,7 @@ from check_service_rules import well_known_actions_verdict, action_tools_verdict
|
|
|
85
91
|
from check_service_rules import opens_in_host_verdict, service_checkout # noqa: E402 - FAA-118
|
|
86
92
|
from check_service_rules import well_known_a2a_verdict, a2a_card_verdict # noqa: E402 - DEC-0122
|
|
87
93
|
import fabric_a2a as fa2 # noqa: E402 - DEC-0122
|
|
94
|
+
import check_service_channel_agent as cac # noqa: E402 - DEC-0150, FAA-197
|
|
88
95
|
|
|
89
96
|
|
|
90
97
|
class _PinnedHTTPS(http.client.HTTPSConnection):
|
|
@@ -248,6 +255,7 @@ class Probe:
|
|
|
248
255
|
return
|
|
249
256
|
try:
|
|
250
257
|
self.wk = json.loads(body)
|
|
258
|
+
self.wk_bytes = len(body) # D4 of the 0.73.0 brief: a well-known answer shares a 2 MiB cap
|
|
251
259
|
except ValueError:
|
|
252
260
|
if self.remote:
|
|
253
261
|
self.add_no_token(no_token, None)
|
|
@@ -638,6 +646,14 @@ class Probe:
|
|
|
638
646
|
self.trace_rule(listing, sent)
|
|
639
647
|
self.events_trace_rule(self.events)
|
|
640
648
|
|
|
649
|
+
def channel_agent_rule(self) -> None:
|
|
650
|
+
"""DEC-0150 (FAA-197): the channel agent's declaration, read from the manifest the descriptor names, else from the
|
|
651
|
+
well-known answer (CA-1); one read as not declared is NOT_RUN with its evidence, never a FAIL (D3), except a string
|
|
652
|
+
shaped like a credential in it or in a copy the probe reads beside it (CA-5)."""
|
|
653
|
+
manifest, _, where = self.load_manifest()
|
|
654
|
+
self.add("channel-agent.declaration", *cac.declaration_verdict(
|
|
655
|
+
manifest, bool(self.d.get("fabricManifest")), where, self.wk, getattr(self, "wk_bytes", None)))
|
|
656
|
+
|
|
641
657
|
def configuration_rule(self) -> None:
|
|
642
658
|
"""DEC-0046: a well-known `configuration` is {slots, resolved} as the schema types it; absent is NOT_RUN."""
|
|
643
659
|
if not isinstance(self.wk, dict) or "configuration" not in self.wk:
|
|
@@ -893,6 +909,7 @@ class Probe:
|
|
|
893
909
|
self.dashboard_page_rules()
|
|
894
910
|
self.login_rules()
|
|
895
911
|
self.interop_rules()
|
|
912
|
+
self.channel_agent_rule()
|
|
896
913
|
verdict, evidence = board_responder_verdict(self.wk, self.board_kit)
|
|
897
914
|
self.add("board.responder", verdict, evidence)
|
|
898
915
|
self.lifecycle_rules()
|