@passioncode-ai/fabric-agent-adapter 0.49.3 → 0.51.1
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 +108 -0
- package/README.md +7 -2
- 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 +29 -11
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/dashboard-links.md +58 -5
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/operator-channel-and-repository.md +11 -3
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/check_dashboard_link.py +8 -6
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +50 -12
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-button.js +5 -4
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json +9 -4
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +5 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +3 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md +58 -5
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard.md +13 -4
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +13 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/estate-record.md +60 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +159 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +8 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/package.md +4 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +14 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/settings-backups.md +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/surfaces-and-auth.md +40 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_link.py +8 -6
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +67 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +371 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a.mjs +170 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-actions.mjs +275 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +3 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-context.mjs +151 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +38 -8
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +31 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs +6 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop-rules.mjs +68 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +31 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-mandate.mjs +247 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-page-links.mjs +144 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-paths.mjs +22 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-share.mjs +30 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +5 -4
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_a2a.py +209 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_actions.py +340 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_context.py +170 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +36 -12
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +36 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py +7 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +242 -11
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop_rules.py +70 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_mandate.py +324 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_page_links.py +559 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py +21 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +9 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_share.py +35 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +6 -4
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +413 -25
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +29 -11
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/dashboard-links.md +58 -5
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/operator-channel-and-repository.md +11 -3
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/check_dashboard_link.py +8 -6
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +87 -10
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/project-board.md +12 -0
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,113 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.51.1 (2026-10-26)
|
|
4
|
+
|
|
5
|
+
The tag `v0.51.0` was never published: its release run stopped at the Node 18 floor, so 0.51.1 is the first npm
|
|
6
|
+
release carrying everything listed under 0.51.0 below.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- The tests of one instance per context (`test/fabric-context.test.mjs`, FAA-125) skip on Linux under a Node that
|
|
11
|
+
cannot bind an abstract socket name exactly (Node 18 and 20), as every other lock test does since FAA-72. The kit
|
|
12
|
+
itself already refused there with a sentence; only the tests lacked the guard.
|
|
13
|
+
- `references/package.md` no longer says the passkey countersignature waits for `org-authority/1`: DEC-0129 decided
|
|
14
|
+
that protocol only as the organization's member list for relay admission, and the countersignature waits for the
|
|
15
|
+
decision that defines the `org-countersign/1` verifier (contract finding on board thread `6c50c84f`).
|
|
16
|
+
|
|
17
|
+
## 0.51.0 (2026-10-26)
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Pinned to the contract release `v0.1.0+2026-10-26.2` (`e6c4fc16`)** (FAA-128). It carries DEC-0122 to DEC-0125;
|
|
22
|
+
`a3a66eb0` and `52c7d798` stay supported. Brief: `docs/evidence/specs/2026-10-26-faa-128-125-repin-a3a66eb-brief.md`.
|
|
23
|
+
- **Narrowings (DEC-0123, FAA-132).** `url_request` / `urlRequest` now refuses a loopback page URL (`http://127.0.0.1`
|
|
24
|
+
and every other spelling of a local address): hand a service's page over as Fabric Dashboards' `open_link`
|
|
25
|
+
(`page_answer` / `pageAnswer` builds it). `check_dashboard_link.py` refuses the legacy `open?service=` link and a
|
|
26
|
+
page path with whitespace, as the contract's `parseDashboardsLink` does. A service that built either may now be
|
|
27
|
+
refused at construction.
|
|
28
|
+
- **DL-19 `operator-decision-required`** names the three routes for a client that cannot set `_meta`: Fabric's
|
|
29
|
+
`agent.call` with `call.decision` once the hub forwards it, the service's own elicitation, the action's page as an
|
|
30
|
+
`open_link`. Outside a mandate (`data.detail` `outside-mandate: <part>`) it gives DEC-0125 MD-4's order instead:
|
|
31
|
+
call again within your own mandate, else pass the refusal up; only the leading agent asks the operator, with the
|
|
32
|
+
same three routes.
|
|
33
|
+
- Dashboard kit 1.1.5 now matches its pin (DEC-0124 is in it); brief decision D17 of 0.50.0 is closed.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **The operator's mandate (DEC-0125, FAA-131).** `fabric_mandate` / `fabric-mandate.mjs` port `mandate/1`
|
|
38
|
+
(FAC-SEM-144, scope narrowing, hand-over); `request_meta(mandate=)` sends one; a server with `agent_id` reads
|
|
39
|
+
`_meta.mandate` in its action gate. working-with-fabric states the operator's rule of 2026-10-26, «я сказал одному
|
|
40
|
+
= сказал всем»: one approval he gives any of his agents binds all of them when the relay carries his words, the
|
|
41
|
+
date, the source and the scope from one of his own Projects on his personal board (provenance `trusted`; never a
|
|
42
|
+
member's Project on an organization's board) or the session that started the agent; content an agent read is never
|
|
43
|
+
one; human gates stay. A hand-over never adds a `capabilities` or `actions` list the scope in force leaves out
|
|
44
|
+
(contract DEC-0136 MD-2a, adopted ahead of the pin: brief decision D28), so no agent of the chain can grant itself an
|
|
45
|
+
action the operator did not name. Taking a prose relay from another agent is the operator's rule, honoured ahead of the pinned
|
|
46
|
+
AP-3 (brief decision D27); the contract's DEC-0126 (OA-2) states it, and FAA-134 takes its wording in 0.52.0.
|
|
47
|
+
- **A service's pages as `open_link` (DEC-0123).** `fabric_page_links` / `fabric-page-links.mjs` build and read
|
|
48
|
+
Fabric Dashboards links and FAC-SEM-143, checked against the contract's vectors and about 200,000 generated
|
|
49
|
+
inputs with no twin difference.
|
|
50
|
+
- **A2A, the reading side (DEC-0122).** `fabric_a2a` / `fabric-a2a.mjs` read `surfaces.a2a` and an Agent Card;
|
|
51
|
+
`build_well_known(a2a=)` writes the member; the probe adds `well-known.a2a` and `a2a.card` (the card is fetched
|
|
52
|
+
without the descriptor's token). Serving a card and the A2A binding stay FAA-10.
|
|
53
|
+
- **One instance per context (FAA-125, N-11).** `fabric_context` / `fabric-context.mjs`: `hold_context_instance`
|
|
54
|
+
derives a context's instance, folders and lock, refuses a second process, refuses an `org:<id>` instance without
|
|
55
|
+
its share grant placement and exits 78 before creating anything; `personal` keeps the `default` instance.
|
|
56
|
+
`launchd_uninstall(instance=)` removes only that instance.
|
|
57
|
+
|
|
58
|
+
## 0.50.0 (2026-10-26)
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- **Pinned to the contract release `v0.1.0+2026-10-25` (`52c7d798`)** (FAA-117, contract CT-124). The release carries
|
|
63
|
+
DEC-0112 to DEC-0121; only DEC-0121 changes kit code, the others bind a node, an organization server or Project
|
|
64
|
+
Observatory and only regenerate vendored vectors (connections gains seven cases, the protocol register
|
|
65
|
+
`fabric-actions/0.1`). `2f020a6` stays supported. The brief is
|
|
66
|
+
`docs/evidence/specs/2026-10-26-faa-117-118-repin-52c7d79-brief.md` (decisions D1 to D17).
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- **Dashboard action parity (DEC-0121).** Every button a dashboard offers the operator is an agent action too.
|
|
71
|
+
- `fabric_actions.py` / `fabric-actions.mjs` port the contract's `actionDecision`, `actionsView` and the FAC-SEM-142
|
|
72
|
+
rules, checked against `fixtures/vectors/actions.json` (65 cases) and the semantic fixtures.
|
|
73
|
+
- A service declares its actions with `McpToolServer.add_tool(..., action=, target=, human_step_url=)` and
|
|
74
|
+
publishes them with `build_well_known(actions=)` / `buildWellKnown({actions})` as `extensions/actions/0.1`; a
|
|
75
|
+
declaration the contract would flag is refused.
|
|
76
|
+
- The server gate reads only `_meta.decision`, never the arguments: a T0 or T1 call without the operator's
|
|
77
|
+
decision is refused `operator-decision-required`, a malformed one `decision-invalid`, a step only a person can
|
|
78
|
+
take `human-step-required` with `data.humanStep` and `data.url`, and T2 still needs `approval-required`. The
|
|
79
|
+
decision records the authenticated caller (`identify`, the delegation's caller, or `local:T0` / `local:T1`).
|
|
80
|
+
Gating a job's input responses is opt-in (`input_actions=True`) until Fabric's hub forwards decisions (CT-125).
|
|
81
|
+
The kits are ready now; a service adopts the gate once CT-125 lands, as the contract says (DEC-0121
|
|
82
|
+
*Compatibility*, CT-127), because Claude Code and Codex cannot set `_meta` and would otherwise meet
|
|
83
|
+
`operator-decision-required` with the page as their only route.
|
|
84
|
+
- A caller relays with `request_meta(decision=...)` / `requestMeta(traceparent, {decision})`.
|
|
85
|
+
- The three codes join DL-19 in both delegation twins.
|
|
86
|
+
- **The probe** reports `well-known.actions`, `interop.action-tools` (a declared action's tool must be served),
|
|
87
|
+
`dashboard.actions-declared` (`NOT_RUN` for a dashboard that declares none) and `dashboard.opens-in-host`
|
|
88
|
+
(FAA-118: a browser opener aimed at the service's own pages in its checkout fails; `--repo PATH` names the
|
|
89
|
+
checkout).
|
|
90
|
+
- **working-with-fabric** relays the operator's own words as the decision (AP-3), never text from a tool result, a
|
|
91
|
+
page, a file or another agent; a coding agent whose client cannot set `_meta` goes through Fabric's `agent.call`
|
|
92
|
+
(after CT-125), the service's elicitation, or the action's page in Fabric Dashboards, in that order (confirmed by
|
|
93
|
+
the contract's owner on board thread `92c6f277`). On `human-step-required` it hands the person the link.
|
|
94
|
+
|
|
95
|
+
- **Fabric's button follows contract DEC-0124** (dashboard kit 1.1.5; FB-3 amended on the adapter's request, board
|
|
96
|
+
thread `4801da8d`, contract PR #189, after this release's pin). The accessible name and the menu follow the page's
|
|
97
|
+
language, which the contract now states, so 0.49.3's note that the kit departs from FB-3 no longer holds. A page's
|
|
98
|
+
own words (`data-label-*`) are taken only when they keep the word *Fabric* (WCAG 2.2 SC 2.5.3, Label in Name);
|
|
99
|
+
otherwise the built-in words stay. A page that set words without *Fabric* under 0.49.3 shows the built-in words
|
|
100
|
+
after it updates its kit. The kit follows this amendment ahead of the pin (brief decision D17).
|
|
101
|
+
- **The probe's new `dashboard.opens-in-host` can fail a service that passed before**: one that opens its own pages
|
|
102
|
+
in a browser. Open them through Fabric Dashboards instead (see the building-fabric-services skill).
|
|
103
|
+
|
|
104
|
+
### Changed (guidance)
|
|
105
|
+
|
|
106
|
+
- **Agent pages open only in Fabric Dashboards** (FAA-118, the operator's rule of 2026-10-24): the rule now sits in
|
|
107
|
+
the body of the three SKILL.md files, with the AGENTS.md block a project carries and a section for an agent that
|
|
108
|
+
has a page and no service descriptor. Manual restore and enabling the operator channel are the operator's
|
|
109
|
+
decision on the page or relayed (D16).
|
|
110
|
+
|
|
3
111
|
## 0.49.3 (2026-10-25)
|
|
4
112
|
|
|
5
113
|
### Fixed
|
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ a service (a descriptor names it as `source.repository`) whose dashboard has no
|
|
|
85
85
|
anywhere else; the [kit reference](plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md)
|
|
86
86
|
has the upgrade steps, which the agent may take itself.
|
|
87
87
|
|
|
88
|
+
Agent pages open only in Fabric Dashboards (the operator's rule, carried in the builder skills since 0.50.0).
|
|
88
89
|
Dashboard handoffs use the host-generated `open_link` as the primary action. The
|
|
89
90
|
three builder skills carry the same [consumer procedure](plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md)
|
|
90
91
|
and a portable `scripts/check_dashboard_link.py` gate for generated renderers.
|
|
@@ -98,7 +99,11 @@ is the MCP tool of its name, long work is a job with a stable id (`fabric.job.ge
|
|
|
98
99
|
`fabric.job.cancel`), a question for a person is an elicitation, and every call carries
|
|
99
100
|
one W3C trace. The kits ship the helpers (`scripts/fabric_interop.py`,
|
|
100
101
|
`scripts/fabric-interop.mjs`), the sample service serves a job end to end, and the probe
|
|
101
|
-
checks the interop rules.
|
|
102
|
+
checks the interop rules. Every dashboard button has a tool (`fabric-actions/0.1`, contract DEC-0121): the
|
|
103
|
+
operator's agent relays their decision in `_meta.decision` (a service adopts the gate once Fabric's hub forwards
|
|
104
|
+
decisions, CT-125; Claude Code and Codex, which cannot set `_meta`, relay through Fabric's `agent.call`, the service's
|
|
105
|
+
own elicitation or the action's page), and the refusals `operator-decision-required`,
|
|
106
|
+
`decision-invalid` and `human-step-required` say what is missing. A job a provider limit paused or stopped, and an effect nobody saw, carry their own codes
|
|
102
107
|
(`quota-exhausted`, `outcome-unknown`) and keys per caller (contract DEC-0087). The estate kits check share grants into
|
|
103
108
|
an organization (`scripts/fabric_share.py`, DEC-0086) and the estate ceremonies: a revision's record rules, a headless
|
|
104
109
|
machine's enroll token, the nearby pairing by a comparison code and the hub's single use of a token
|
|
@@ -275,7 +280,7 @@ Scaffolding is non-destructive by default. It writes only the paths declared in
|
|
|
275
280
|
The default pin for new bundles is [`fabric-contract.lock.json`](fabric-contract.lock.json):
|
|
276
281
|
|
|
277
282
|
- version: `0.1.0`
|
|
278
|
-
- commit: `
|
|
283
|
+
- commit: `e6c4fc16b415eec3190dd34d924d269405359dc9`
|
|
279
284
|
|
|
280
285
|
Every other mention of the default contract revision (this section, the skills' metadata, the
|
|
281
286
|
skill card, `adapt_project.py`) must equal it; `python3 test/validate.py` fails a tree
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.1",
|
|
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.51.1",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -5,9 +5,9 @@ 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.51.1"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "e6c4fc16b415eec3190dd34d924d269405359dc9"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Adapting projects to Fabric
|
|
@@ -76,7 +76,7 @@ Use exactly:
|
|
|
76
76
|
|
|
77
77
|
- contract version `0.1.0`;
|
|
78
78
|
- repository `https://github.com/passioncode-ai/fabric-agent-contract`;
|
|
79
|
-
- commit `
|
|
79
|
+
- commit `e6c4fc16b415eec3190dd34d924d269405359dc9`.
|
|
80
80
|
|
|
81
81
|
This is the default for new bundles. When checking an issued legacy bundle, preserve its
|
|
82
82
|
explicit supported lock and use that exact clean checkout. Never silently upgrade or
|
|
@@ -218,9 +218,9 @@ not a connected provider.
|
|
|
218
218
|
If the agent has a human stop (a choice, an approval, a confirmation) or emits `notify: true`
|
|
219
219
|
events, propose its operator channel (`fabric-operator-channel/0.1`, OC-11) to the operator once,
|
|
220
220
|
now, as [the operator channel and the repository standard](references/operator-channel-and-repository.md)
|
|
221
|
-
describes: the operator's four steps, the answer recorded and never asked again,
|
|
222
|
-
token and enabling the channel
|
|
223
|
-
skips this step.
|
|
221
|
+
describes: the operator's four steps, the answer recorded and never asked again, the bot and the
|
|
222
|
+
token left to the person, and enabling the channel to the operator's decision (on the page or
|
|
223
|
+
relayed, DEC-0121). An agent with neither stops nor notify events skips this step.
|
|
224
224
|
|
|
225
225
|
## The repository around the provider
|
|
226
226
|
|
|
@@ -245,8 +245,26 @@ Report:
|
|
|
245
245
|
Never summarize the outcome as “Fabric-compatible” unless all required admission gates
|
|
246
246
|
passed against a real provider and the project binding is valid.
|
|
247
247
|
|
|
248
|
-
##
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
## Agent pages open only in Fabric Dashboards
|
|
249
|
+
|
|
250
|
+
The operator's rule (2026-10-24) for every page of an agent or a local Fabric service, in any host: a
|
|
251
|
+
link in an answer or a notification, `<tool> dashboard`, a completion message, a page the agent opens
|
|
252
|
+
itself. Hand over the `open_link` the `fabric-dashboards` MCP's `link` tool returns for the exact
|
|
253
|
+
registered service key (`list_services`, never guessed) and the page's path; open it only with the
|
|
254
|
+
host's `open` and `fallback=never`. Never `open <url>`, `open -a Safari`, `xdg-open`,
|
|
255
|
+
`webbrowser.open` or `shell.openExternal` aimed at the agent's pages. A browser only on a confirmed
|
|
256
|
+
`not_installed` host; an installed host that failed to open is reported, never replaced by HTTP.
|
|
257
|
+
Links carry no token or login code.
|
|
258
|
+
|
|
259
|
+
The agent's `AGENTS.md` carries this as its dashboard rule block, and its checks run the adapter's link gate
|
|
260
|
+
(`scripts/check_dashboard_link.py` from this skill's own directory; it is not copied into the project) on every
|
|
261
|
+
completion and notification action before delivery:
|
|
262
|
+
[dashboard links](references/dashboard-links.md) has the block, the gate's input and the remote case.
|
|
263
|
+
Headless agents need no dashboard.
|
|
264
|
+
|
|
265
|
+
## An agent with a page and no service descriptor
|
|
266
|
+
|
|
267
|
+
A local page no service descriptor names cannot open in Fabric Dashboards. Never open it in a browser
|
|
268
|
+
instead: make the agent a `fabric-service/0.1` service with `building-fabric-services` (the descriptor,
|
|
269
|
+
the well-known document, the login-code routes and a declared dashboard), and until that lands file a
|
|
270
|
+
board row for it and say the page waits on it.
|
|
@@ -5,6 +5,19 @@ an existing Fabric service dashboard to a person. This also applies to generated
|
|
|
5
5
|
agent instructions and completion messages. Headless agents need no dashboard;
|
|
6
6
|
API origins, external docs and OAuth links are not dashboard actions.
|
|
7
7
|
|
|
8
|
+
The rule (the operator's, 2026-10-24): every page of an agent or a local Fabric
|
|
9
|
+
service opens only in Fabric Dashboards, never in Safari, Dia, Chrome or any
|
|
10
|
+
other browser, unless Fabric Dashboards is confirmed not installed.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- Resolve, then hand over
|
|
15
|
+
- The block a generated AGENTS.md carries
|
|
16
|
+
- An agent with a page and no service descriptor
|
|
17
|
+
- Device and channel
|
|
18
|
+
- Portable output gate
|
|
19
|
+
- Degradation
|
|
20
|
+
|
|
8
21
|
## Resolve, then hand over
|
|
9
22
|
|
|
10
23
|
1. Discover the target computer and exact registered `service.id.instance`.
|
|
@@ -20,9 +33,12 @@ API origins, external docs and OAuth links are not dashboard actions.
|
|
|
20
33
|
compatible host resolver or report the limitation, not presumed absence.
|
|
21
34
|
4. A request for a link opens nothing. A request to open uses the host `open`
|
|
22
35
|
tool/approved opener, which starts or focuses the existing Fabric Dashboards
|
|
23
|
-
and reuses the service view
|
|
24
|
-
permits one only for confirmed absence. Discover schema support
|
|
25
|
-
`open` implementations may silently fall back on failure and are
|
|
36
|
+
and reuses the service view, with `fallback=never`: it forbids a browser.
|
|
37
|
+
`if_absent` permits one only for confirmed absence. Discover schema support
|
|
38
|
+
first: older `open` implementations may silently fall back on failure and are
|
|
39
|
+
not strict. Never
|
|
40
|
+
`open <url>`, `open -a Safari`, `xdg-open`, `start <url>`, `webbrowser.open`
|
|
41
|
+
or `shell.openExternal` aimed at the service's pages.
|
|
26
42
|
5. An installed host that failed to open is **not absent**. Report the failure;
|
|
27
43
|
do not silently launch HTTP in a browser, a second server, `npm run dev`, or
|
|
28
44
|
another standalone dashboard. A stopped backend stays on its host status/Start
|
|
@@ -31,6 +47,40 @@ API origins, external docs and OAuth links are not dashboard actions.
|
|
|
31
47
|
not page readiness, a successful login, or a completed job. Links carry no
|
|
32
48
|
bearer tokens or login codes. The host handles dashboard authentication.
|
|
33
49
|
|
|
50
|
+
## The block a generated AGENTS.md carries
|
|
51
|
+
|
|
52
|
+
An agent with a page carries this block in its `AGENTS.md` (its `CLAUDE.md` reads
|
|
53
|
+
it through `@AGENTS.md`), beside its browser rule, and its completion and
|
|
54
|
+
notification renderers follow it:
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
## Pages open only in Fabric Dashboards
|
|
58
|
+
|
|
59
|
+
Every page of this agent (its dashboard, a job, an approval, a report) opens in
|
|
60
|
+
Fabric Dashboards, never in a browser. Resolve the registered service key with
|
|
61
|
+
the fabric-dashboards MCP (`list_services`, never guessed) and hand over the
|
|
62
|
+
`open_link` its `link` tool returns for the page's path; to open it, call the
|
|
63
|
+
host's `open` with `fallback=never`. Never `open <url>`, `open -a Safari`,
|
|
64
|
+
`xdg-open`, `start <url>`, `webbrowser.open` or `shell.openExternal` on this
|
|
65
|
+
agent's pages. A browser only when `host_status` confirms `not_installed`; an
|
|
66
|
+
installed host that failed to open is reported, not replaced by HTTP. Links
|
|
67
|
+
carry no token or login code. Every completion and notification action passes
|
|
68
|
+
the Fabric Agent Adapter's link gate before delivery: `check_dashboard_link.py`
|
|
69
|
+
in its `building-fabric-services/scripts`, run from that skill's directory;
|
|
70
|
+
where it cannot run, the action is compared by hand and the check is NOT_RUN.
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The project's checks run the gate below on each renderer's action, and a test
|
|
74
|
+
holds a raw-HTTP primary action beside an available host refused.
|
|
75
|
+
|
|
76
|
+
## An agent with a page and no service descriptor
|
|
77
|
+
|
|
78
|
+
Fabric Dashboards opens only a page a service descriptor names. An agent that
|
|
79
|
+
serves a local page without one cannot be opened there, and a browser is not the
|
|
80
|
+
workaround. Make it a `fabric-service/0.1` service (`building-fabric-services`:
|
|
81
|
+
the descriptor, the well-known document, the login-code routes and a declared
|
|
82
|
+
dashboard); until that lands, file a board row for it and say the page waits on it.
|
|
83
|
+
|
|
34
84
|
## Device and channel
|
|
35
85
|
|
|
36
86
|
A custom scheme opens on the device receiving it. A phone's localhost is not the
|
|
@@ -90,5 +140,8 @@ or instructions alone do not prove all final answers from every agent are filter
|
|
|
90
140
|
|
|
91
141
|
Syntax is owned by Fabric Dashboards and `@passioncode-ai/fabric-service-host`:
|
|
92
142
|
[ADR-0005](https://github.com/passioncode-ai/fabric-dashboards/blob/51a7a80acf42781d7bec304cc87c655d48cc309b/docs/adr/0005-service-links.md).
|
|
93
|
-
The gate accepts
|
|
94
|
-
|
|
143
|
+
The gate accepts only the service form, `fabric-dashboards://service/SERVICE_ID.INSTANCE`
|
|
144
|
+
with at most one `path`; since 0.51.0 it refuses the legacy `open?service=` form, as contract
|
|
145
|
+
DEC-0123 (PL-1, checker rule `FAC-SEM-143`) and its vectors do. A host that still returns the
|
|
146
|
+
legacy form fails the gate: report it as an installed host that did not open the page. The gate
|
|
147
|
+
does not generate links or redefine the Fabric wire contract.
|
|
@@ -26,9 +26,12 @@ bare `/command` in a group is not addressed), and a channel nobody receives on i
|
|
|
26
26
|
|
|
27
27
|
Record the answer (`accepted`, `declined` or `later`) in the agent's state and in its conformance
|
|
28
28
|
report, and do not ask again; an agent that serves `surfaces.operatorChannel` also shows it as
|
|
29
|
-
`proposal` in its status document. Creating the bot
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
`proposal` in its status document. Creating the bot and putting its token into the secret store
|
|
30
|
+
stay the person's (a `secret` step, contract DEC-0121 AP-4): never create the bot, or ask for or
|
|
31
|
+
store the token's value. Enabling the channel, and removing a webhook found on its token, are the
|
|
32
|
+
operator's decision, taken by them on the agent's page or relayed to its agent in their own words
|
|
33
|
+
with `_meta.decision` (OC-1, OC-2, DEC-0121 AP-2); never enable it on your own account. The default
|
|
34
|
+
pin carries DEC-0034 and DEC-0035: a served status document is
|
|
32
35
|
checked against the pinned `schemas/operator-channel-status.schema.json`; the channel's runtime
|
|
33
36
|
rules have no probe rule here yet, so report them `NOT_RUN`. An agent with neither stops nor notify
|
|
34
37
|
events skips this.
|
|
@@ -49,6 +52,11 @@ For a PassionCode.ai repository, the agent's repository follows the organization
|
|
|
49
52
|
- an `AGENTS.md` that opens with the template's *Read first* block and closes with *After work*,
|
|
50
53
|
and a `CLAUDE.md` whose first line is `@AGENTS.md`.
|
|
51
54
|
|
|
55
|
+
Whoever owns the repository, an agent with a page gets the dashboard rule block in its `AGENTS.md`
|
|
56
|
+
(pages open only in Fabric Dashboards; the block is in `references/dashboard-links.md`), and its
|
|
57
|
+
checks run the adapter's link gate (`scripts/check_dashboard_link.py` from the skill's own directory, not a copy in
|
|
58
|
+
the project).
|
|
59
|
+
|
|
52
60
|
org-index `scripts/check_format.py` reports 0 findings for it before it is called done. An agent
|
|
53
61
|
someone builds for themselves is not a PassionCode.ai repository: its licence is its owner's
|
|
54
62
|
choice, nothing about it is published or listed by the organization, and none of these files is
|
package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py
CHANGED
|
@@ -22,10 +22,10 @@ import fabric_secrets as _secrets # noqa: E402 - the contract's credential dete
|
|
|
22
22
|
|
|
23
23
|
CONTRACT_VERSION = "0.1.0"
|
|
24
24
|
CONTRACT_REPOSITORY = "https://github.com/passioncode-ai/fabric-agent-contract"
|
|
25
|
-
CONTRACT_COMMIT = "
|
|
25
|
+
CONTRACT_COMMIT = "e6c4fc16b415eec3190dd34d924d269405359dc9"
|
|
26
26
|
# #region supported-contract-revisions — docs: README.md#contract-pin
|
|
27
27
|
# Only this declaration may name a legacy revision in live files.
|
|
28
|
-
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "87d384ffce2757081b7ab227e5dad3dddd08328f", "0a4ce773c4b9e6bec40c6387eb3f988af7152c0e", "e742016dc396aa31e5a13a893489e43f15786c69", "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0", "c55f2d5a11c9a0197e958e87212fca7ae1154769", "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
28
|
+
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "a3a66eb0052043847f6556348e37d34ca873a629", "52c7d798b9f4eb784eb4e29e717038a8912c759d", "2f020a696453ae299b123517f14957f6a1354379", "87d384ffce2757081b7ab227e5dad3dddd08328f", "0a4ce773c4b9e6bec40c6387eb3f988af7152c0e", "e742016dc396aa31e5a13a893489e43f15786c69", "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0", "c55f2d5a11c9a0197e958e87212fca7ae1154769", "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
29
29
|
# #endregion supported-contract-revisions
|
|
30
30
|
INTEROP_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/interop/0.1"
|
|
31
31
|
MCP_REVISION = "2026-07-28"
|
|
@@ -74,7 +74,9 @@ def login_path(path):
|
|
|
74
74
|
|
|
75
75
|
def safe_path(path):
|
|
76
76
|
return (isinstance(path, str) and path.startswith('/') and not path.startswith('//')
|
|
77
|
-
and len(path) <= 2048 and not re.search(r'[\\\x00-\x1f\x7f]', path)
|
|
77
|
+
and len(path) <= 2048 and not re.search(r'[\\\x00-\x1f\x7f]', path)
|
|
78
|
+
# JavaScript's whitespace (\s), which the contract's parseDashboardsLink refuses in a page (DEC-0123)
|
|
79
|
+
and not re.search('[ \u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]', path))
|
|
78
80
|
|
|
79
81
|
|
|
80
82
|
def check(data):
|
|
@@ -87,11 +89,11 @@ def check(data):
|
|
|
87
89
|
require(not re.search(r'[\\\x00-\x20\x7f]', native + http), 'unsafe_url')
|
|
88
90
|
deep, plain = urlsplit(native), urlsplit(http)
|
|
89
91
|
require(deep.scheme == 'fabric-dashboards' and not deep.username and not deep.password and not deep.port and not deep.fragment, 'invalid_deep_link')
|
|
90
|
-
query
|
|
91
|
-
if deep.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
# An empty query is no fields: Python 3.9's strict parse_qs raises on '' where 3.11 and later answer {}.
|
|
93
|
+
query = parse_qs(deep.query, keep_blank_values=True, strict_parsing=True) if deep.query else {}
|
|
94
|
+
# DEC-0123 PL-1: only the service form; the legacy open?service= link is refused (FAC-SEM-143, since 0.51.0).
|
|
95
|
+
require(deep.netloc == 'service', 'not_service_link')
|
|
96
|
+
require(deep.path in ('/' + service, '/' + service + '/') and set(query) <= {'path'}, 'wrong_service_or_parameter')
|
|
95
97
|
require('path' not in query or len(query['path']) == 1, 'duplicate_path')
|
|
96
98
|
page = query.get('path', [None])[0]
|
|
97
99
|
require(page is None or safe_path(page), 'unsafe_path')
|
|
@@ -14,10 +14,10 @@ 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.51.1"
|
|
18
18
|
contract-version: "0.1.0"
|
|
19
19
|
extension: "fabric-service/0.1"
|
|
20
|
-
extension-commit: "
|
|
20
|
+
extension-commit: "e6c4fc16b415eec3190dd34d924d269405359dc9"
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# Building Fabric services
|
|
@@ -70,9 +70,10 @@ Answer before writing code, and record the answers in the project README:
|
|
|
70
70
|
| Caller | Surface | Why |
|
|
71
71
|
|---|---|---|
|
|
72
72
|
| Another agent on this machine | MCP `2026-07-28`, `streamable-http`, at `/mcp` on the service origin, token in a header | one process serves every session; stdio-per-session once left twenty stray servers on this machine |
|
|
73
|
-
| The operator or a script | a CLI: `<tool> service status\|start\|stop\|restart`, `<tool> dashboard
|
|
73
|
+
| The operator or a script | a CLI: `<tool> service status\|start\|stop\|restart`, `<tool> dashboard` (opens only in Fabric Dashboards, below), `<tool> doctor --json` | every verb delegates to launchd and the well-known document, never to its own process table |
|
|
74
74
|
| A remote agent | A2A `1.0` over HTTPS, or MCP behind an authenticated gateway | loopback reachability is not authorization |
|
|
75
|
-
|
|
|
75
|
+
| An A2A peer on this computer | `surfaces.a2a` names a public Agent Card, served without the token; its interface URLs are loopback (DEC-0122); the kits read it, serving one is FAA-10 | the card carries no credential, process member or required Fabric extension |
|
|
76
|
+
| The dashboard page | same-origin REST under `/api`, session cookie plus a custom request header; every button on it also a tool on the MCP surface (Step 5) | the CSRF defence all four existing dashboards use |
|
|
76
77
|
|
|
77
78
|
Read [the surfaces and auth reference](references/surfaces-and-auth.md) when wiring
|
|
78
79
|
MCP registration into a client config, the login flow or the CSRF header.
|
|
@@ -248,6 +249,16 @@ and declare it with `extensions=fs.dashboard_extension()`. Read
|
|
|
248
249
|
declaration and how to upgrade a dashboard built before the kit: an upgrade you may make yourself,
|
|
249
250
|
which the plugin's session-start notice offers in a repository that owns the service.
|
|
250
251
|
|
|
252
|
+
**Every button has a tool** (`fabric-actions/0.1`, contract DEC-0121 AP-1). Each action the page lets a
|
|
253
|
+
person take is a tool on the MCP surface with the same effect, checks, audit record and an idempotency key,
|
|
254
|
+
registered with `server.add_tool(tool, handler, action={id, title, tool, gate})` (`gate` is `none`, `relayed`
|
|
255
|
+
or `human` with its `humanStep`) and declared with `build_well_known(actions=server.action_table())` under
|
|
256
|
+
`extensions/actions/0.1`. A `relayed` action called by the operator's own agent with their decision in
|
|
257
|
+
`_meta.decision` is the operator's act: never answer it "operator session required" or send them to the page.
|
|
258
|
+
A service adopts the relayed gate once Fabric's hub forwards decisions (CT-125), as the contract says; until then its tools
|
|
259
|
+
answer as today. Read the interop reference's *Actions* section for when to adopt, the gate, its hooks and its
|
|
260
|
+
refusals.
|
|
261
|
+
|
|
251
262
|
**Say what the agent uses** (`fabric-connections/0.1`, DEC-0096) so Fabric Dashboards draws its chain: the other
|
|
252
263
|
agents, models, connectors, stores and channels, each with its state, from
|
|
253
264
|
`connections_extension()` / `connectionsExtension()` in `fabric_connections`. Never a credential in it, never a call
|
|
@@ -283,10 +294,15 @@ python3 <skill-dir>/scripts/check_service.py <id>[.<instance>]
|
|
|
283
294
|
It reports `PASS`, `FAIL` or `NOT_RUN` per rule (descriptor, port claim, well-known
|
|
284
295
|
shape, identity, latency, Host/Origin/cross-site guards, loopback bind, token file,
|
|
285
296
|
events auth and shape, single-use login, state outside code, instance lock, plist,
|
|
286
|
-
launchd pid equals answering pid, `dashboard.declared` (ED-9),
|
|
297
|
+
launchd pid equals answering pid, `dashboard.declared` (ED-9), `well-known.actions` (DEC-0121),
|
|
298
|
+
`dashboard.actions-declared` (`NOT_RUN` when a dashboard declares no actions), `dashboard.opens-in-host` (no browser
|
|
299
|
+
opener aimed at the service's pages in its checkout; `--repo PATH` names the checkout, and a service installed
|
|
300
|
+
from a release folder needs it), and the `interop.*` rules:
|
|
287
301
|
manifest link, capability list, tools equal to the manifest, job tools, unknown job, trace
|
|
288
|
-
propagation, event trace pairs,
|
|
289
|
-
|
|
302
|
+
propagation, event trace pairs, `interop.action-tools` (every declared action's tool is served), `well-known.a2a` and
|
|
303
|
+
`a2a.card` (DEC-0122: the card is fetched without the token and its interfaces are never called; the surfaces
|
|
304
|
+
reference's *A2A for remote agents* section), and
|
|
305
|
+
`board.responder` for a service that declares the project board) and exits 1 on any `FAIL`. A `NOT_RUN` is not a pass;
|
|
290
306
|
name it in the report. A service with a dashboard also runs the layout probe,
|
|
291
307
|
`node <skill-dir>/scripts/check_dashboard_layout.mjs --service <id>` (WebKit at 360, 480, 768
|
|
292
308
|
and 1280 px; needs Playwright, else `NOT_RUN` and exit 3: nothing was measured).
|
|
@@ -328,7 +344,8 @@ first commit:
|
|
|
328
344
|
- an `AGENTS.md` that opens with the template's *Read first* block and closes with *After work*,
|
|
329
345
|
and a `CLAUDE.md` whose first line is `@AGENTS.md`.
|
|
330
346
|
|
|
331
|
-
|
|
347
|
+
Whoever owns the repository, an agent with a page gets the dashboard rule block in its `AGENTS.md`
|
|
348
|
+
(below). org-index `scripts/check_format.py` reports 0 findings for it before it is called done. **An agent
|
|
332
349
|
someone builds for themselves is not a PassionCode.ai repository:** its licence is its owner's
|
|
333
350
|
choice, nothing about it is published or listed by the organization, and none of these files is
|
|
334
351
|
required of it, though the verified MCP quick start is still how anyone learns to drive it.
|
|
@@ -418,8 +435,29 @@ the probe table verbatim with every `NOT_RUN` explained; the lock and kill-9 res
|
|
|
418
435
|
with pids; and the one next command. Never call a service conformant while the probe
|
|
419
436
|
reports a `FAIL`.
|
|
420
437
|
|
|
421
|
-
##
|
|
438
|
+
## Agent pages open only in Fabric Dashboards
|
|
439
|
+
|
|
440
|
+
The operator's rule (2026-10-24) for every page of an agent or a local Fabric service, in any host: a link in an
|
|
441
|
+
answer or a notification, `<tool> dashboard`, a completion message, a page the agent opens itself.
|
|
442
|
+
|
|
443
|
+
1. Resolve the exact registered service key (`id.instance`) with the `fabric-dashboards` MCP (`list_services`);
|
|
444
|
+
never guess it from a project name or a port.
|
|
445
|
+
2. Hand over the `open_link` its `link` tool returns for the service and the page's path, as the primary action.
|
|
446
|
+
3. To open it, use the host's `open` with `fallback=never`. Never `open <url>`, `open -a Safari`, `xdg-open`,
|
|
447
|
+
`start <url>`, `webbrowser.open` or `shell.openExternal` aimed at the service's pages.
|
|
448
|
+
4. A browser only on a confirmed `not_installed` host (`host_status`); an installed host that failed to open is
|
|
449
|
+
reported, never replaced by HTTP.
|
|
450
|
+
5. Links carry no token or login code: the host signs in.
|
|
451
|
+
|
|
452
|
+
Run `scripts/check_dashboard_link.py` (from this skill's own directory; it is not copied into the project) on an
|
|
453
|
+
action before it is printed or opened, and have the project's checks run it for every completion and notification
|
|
454
|
+
renderer. The generated `AGENTS.md` carries the rule as its dashboard
|
|
455
|
+
rule block; [dashboard links](references/dashboard-links.md) has the block, the gate's input and the remote case. The
|
|
456
|
+
probe's `dashboard.opens-in-host` fails a tracked file that opens the dashboard with a browser opener. Headless agents
|
|
457
|
+
need no dashboard.
|
|
458
|
+
|
|
459
|
+
## An agent with a page and no service descriptor
|
|
422
460
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
and
|
|
461
|
+
A local page no service descriptor names cannot open in Fabric Dashboards. Never open it in a browser instead:
|
|
462
|
+
make the agent a `fabric-service/0.1` service (this skill: the descriptor, the well-known document, the login-code
|
|
463
|
+
routes and a declared dashboard), and until that lands file a board row for it and say the page waits on it.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.5 · Fabric's button (Fabric Agent Contract DEC-0040, FB-1…FB-8, FL-1…FL-6)
|
|
2
2
|
Load it same-origin, after fabric-dashboard.css, with the service it opens Fabric on:
|
|
3
3
|
<script src="fabric-button.js" defer data-service="example-agent.default" data-service-name="Example Agent"
|
|
4
4
|
data-project="project-a" data-project-name="Project A"></script>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
(function (root) {
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var VERSION = '1.1.
|
|
14
|
+
var VERSION = '1.1.5';
|
|
15
15
|
var COOKIE = 'fabric_button';
|
|
16
16
|
var GET_FABRIC = 'https://passioncode.ai/fabric';
|
|
17
17
|
var ABSENT_AFTER_MS = 1500;
|
|
@@ -165,13 +165,14 @@
|
|
|
165
165
|
absent: 'Fabric \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d. \u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u0435\u0433\u043e \u043d\u0430' }
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
-
/** The labels for a page language, each one replaced by a non-blank string the page gives (data-label-*)
|
|
168
|
+
/** The labels for a page language, each one replaced by a non-blank string the page gives (data-label-*) that keeps
|
|
169
|
+
the word Fabric: the visible label stays inside the name and each item (DEC-0124, WCAG 2.2 SC 2.5.3). */
|
|
169
170
|
function labelsFor(lang, overrides) {
|
|
170
171
|
var base = LABELS[/^ru(-|$)/i.test(String(lang || '')) ? 'ru' : 'en'];
|
|
171
172
|
var out = {};
|
|
172
173
|
Object.keys(base).forEach(function (k) {
|
|
173
174
|
var own = overrides ? overrides[k] : undefined;
|
|
174
|
-
out[k] = typeof own === 'string' && own.trim() ? own.trim() : base[k];
|
|
175
|
+
out[k] = typeof own === 'string' && own.trim() && own.indexOf('Fabric') >= 0 ? own.trim() : base[k];
|
|
175
176
|
});
|
|
176
177
|
return out;
|
|
177
178
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.5 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
|
|
2
2
|
A Fabric service dashboard shown inside a host pane: usable from 360 CSS px up, navigation always
|
|
3
3
|
reachable, wide content in its own scroll box, one vertical scroller, appearance from the host.
|
|
4
4
|
Copy this file next to fabric-dashboard.js; do not edit it in place. Put the page's own rules in
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.5 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
|
|
2
2
|
Load it same-origin with <script src="fabric-dashboard.js" defer></script>: no inline script, no
|
|
3
3
|
eval, nothing from a CDN. It applies the host's appearance (ED-6, ED-8), folds navigation that
|
|
4
4
|
does not fit into a More menu (ED-3), makes wide boxes keyboard-reachable (ED-4) and keeps
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
10
|
var KIT = 'fabric-dashboard-kit';
|
|
11
|
-
var VERSION = '1.1.
|
|
11
|
+
var VERSION = '1.1.5';
|
|
12
12
|
/* fabric-dashboard-kit:theme-ids:begin */
|
|
13
13
|
var THEMES = ['graphite', 'fabric', 'paper', 'forest', 'ocean', 'ember', 'contrast'];
|
|
14
14
|
/* fabric-dashboard-kit:theme-ids:end */
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabric-dashboard-kit",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"profile": "fabric-dashboard/0.1",
|
|
5
5
|
"decision": "DEC-0036",
|
|
6
6
|
"declarationKey": "https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"contrast"
|
|
16
16
|
],
|
|
17
17
|
"files": {
|
|
18
|
-
"fabric-dashboard.css": "
|
|
19
|
-
"fabric-dashboard.js": "
|
|
20
|
-
"fabric-button.js": "
|
|
18
|
+
"fabric-dashboard.css": "cc7a96fa2c5eeb03d113e7a543ed88d43ce78c2808c411de199ea0fc6d55b957",
|
|
19
|
+
"fabric-dashboard.js": "5df01193c590a1d8aa82a521954902fecf2d7f655df482165f90d7291b00087f",
|
|
20
|
+
"fabric-button.js": "e945b3252f9a246826d06dbe7bd4be66e82d539a33728c3d3043fd61d4cbd681",
|
|
21
21
|
"themes.json": "511839f1a1a83eb37fadfd132791474497d5c28c5091700b9aa31ad076e359b5"
|
|
22
22
|
},
|
|
23
23
|
"history": {
|
|
@@ -49,6 +49,11 @@
|
|
|
49
49
|
"fabric-dashboard.css": "c9367aad04c662547aec61e67e10b99d80ec1d1c4618b4473bc2db882d80db94",
|
|
50
50
|
"fabric-dashboard.js": "5f157d185d9b04e9a11e680399503bbae924520ed0c112b734bf59fc8ee6bb49",
|
|
51
51
|
"fabric-button.js": "2906d3533635df2ed1f2f071abe00238d30ea81666ff34c3456b376526b66859"
|
|
52
|
+
},
|
|
53
|
+
"1.1.5": {
|
|
54
|
+
"fabric-dashboard.css": "cc7a96fa2c5eeb03d113e7a543ed88d43ce78c2808c411de199ea0fc6d55b957",
|
|
55
|
+
"fabric-dashboard.js": "5df01193c590a1d8aa82a521954902fecf2d7f655df482165f90d7291b00087f",
|
|
56
|
+
"fabric-button.js": "e945b3252f9a246826d06dbe7bd4be66e82d539a33728c3d3043fd61d4cbd681"
|
|
52
57
|
}
|
|
53
58
|
}
|
|
54
59
|
}
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md
CHANGED
|
@@ -101,7 +101,9 @@ version is still read and never written; delete it once its messages are past th
|
|
|
101
101
|
- Replace the example knowledge with the product's own, and run real past questions through it ([practices](../../../creating-fabric-agents/references/practices.md#judges-and-evals), *Judges
|
|
102
102
|
and evals*): count handoffs and read a sample of replies.
|
|
103
103
|
- Show spend: `fabric_usage.usage_report` over the ledger, or `fabric_openrouter.totals`.
|
|
104
|
-
- One decision per message id holds in one process
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
- One decision per message id holds in one process. Each process reads `decisions.jsonl` once and keeps the index in
|
|
105
|
+
memory, so a second process writing the same state folder is not seen: a service runs one instance per context with
|
|
106
|
+
`fabric_context.hold_context_instance` (Node: `holdContextInstance`) and points `stateDir` at that instance's data
|
|
107
|
+
folder, so a second copy for the same context exits 75 and an organization's copy keeps its own folder
|
|
108
|
+
([one instance per context](../../references/estate-record.md#one-instance-per-context-the-helper)).
|
|
107
109
|
- Set the outbox's retention and schedule `prune`.
|