@passioncode-ai/fabric-agent-adapter 0.46.0 → 0.47.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 +33 -0
- package/README.md +1 -1
- 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 +3 -3
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-button.js +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +40 -8
- 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/references/dashboard-kit.md +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/estate-record.md +35 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs +47 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +3 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py +51 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +161 -9
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.47.0 (2026-10-23)
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Pinned to contract `87d384f`** (FAA-105; `0a4ce77` stays supported): DEC-0105 (the home-path detector and a node
|
|
8
|
+
summary's silence) and DEC-0106 (calls between machines of one estate). Every vendored vector is regenerated from
|
|
9
|
+
the contract's own functions at the pin.
|
|
10
|
+
- **The estate reader reads a machine's `profile`** (DEC-0106), both twins. `FAC-SEM-134` joins the record's rules:
|
|
11
|
+
a profile is `full`, `member` or `view`; only a `full` machine carries a `hubKey`; a `view` machine places no agent,
|
|
12
|
+
holds no secret and fills none. `verify_estate_record` / `verifyEstateRecord` refuses a revision that breaks it
|
|
13
|
+
(`rule-violation`). New: `machine_profile(record, machine_id)` / `machineProfile(record, machineId)` and
|
|
14
|
+
`MACHINE_PROFILES`, held to the contract's profile vectors and hostile inputs.
|
|
15
|
+
- **`profile-forbids` is a DL-19 refusal code** in both delegation kits (403), with its message.
|
|
16
|
+
- **The protocol register gains `fabric-agent-call/1`**, both twins.
|
|
17
|
+
- `references/estate-record.md` gains *Machine profiles*; `references/delegation.md` and `references/protocol.md` name
|
|
18
|
+
DEC-0106. Placing a relay caller, judging a call by profile and sealing it stay a relay node's duties, not the kit's
|
|
19
|
+
yet (FAA-106). DEC-0105 changes no kit: the kits do not port the activity rules' home-path detector.
|
|
20
|
+
|
|
21
|
+
## 0.46.1 (2026-10-23)
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **Dashboard kit 1.1.3: the section navigation no longer leaves a half-cut link beside More** (FAA-104, a finding
|
|
26
|
+
from research-agent on board thread `288afbce`). `foldNav` measured the fit, then wrote the summary (`More: <current>`
|
|
27
|
+
or `More (N)`), whose longer text narrowed the list after the measurement; it now measures with the summary in place,
|
|
28
|
+
and also catches a link that sticks out by a fraction of a pixel. The summary follows `aria-current` when a page
|
|
29
|
+
moves it (a `MutationObserver`), and `FabricDashboard.refreshNav(nav)` refits after a page changes the links' text.
|
|
30
|
+
A refit keeps keyboard focus on the link it was on, `aria-current="false"` (as React renders it) is not current, and
|
|
31
|
+
folding a nav a second time refits it instead of adding observers.
|
|
32
|
+
Held by a WebKit test that sweeps 360 to 640 px at every current section (`test/fabric-dashboard-fold.test.mjs`, run
|
|
33
|
+
with `FABRIC_PLAYWRIGHT`). Services pick it up by re-vendoring the kit (`dashboard_kit.py`; the session-start notice
|
|
34
|
+
names an older copy).
|
|
35
|
+
|
|
3
36
|
## 0.46.0 (2026-10-23)
|
|
4
37
|
|
|
5
38
|
### Changed
|
package/README.md
CHANGED
|
@@ -274,7 +274,7 @@ Scaffolding is non-destructive by default. It writes only the paths declared in
|
|
|
274
274
|
The default pin for new bundles is [`fabric-contract.lock.json`](fabric-contract.lock.json):
|
|
275
275
|
|
|
276
276
|
- version: `0.1.0`
|
|
277
|
-
- commit: `
|
|
277
|
+
- commit: `87d384ffce2757081b7ab227e5dad3dddd08328f`
|
|
278
278
|
|
|
279
279
|
Every other mention of the default contract revision (this section, the skills' metadata, the
|
|
280
280
|
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.47.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.47.0",
|
|
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.47.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "87d384ffce2757081b7ab227e5dad3dddd08328f"
|
|
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 `87d384ffce2757081b7ab227e5dad3dddd08328f`.
|
|
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
|
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 = "87d384ffce2757081b7ab227e5dad3dddd08328f"
|
|
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, "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, "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"
|
|
@@ -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.47.0"
|
|
18
18
|
contract-version: "0.1.0"
|
|
19
19
|
extension: "fabric-service/0.1"
|
|
20
|
-
extension-commit: "
|
|
20
|
+
extension-commit: "87d384ffce2757081b7ab227e5dad3dddd08328f"
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# Building Fabric services
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.3 · 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>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
(function (root) {
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
-
var VERSION = '1.1.
|
|
13
|
+
var VERSION = '1.1.3';
|
|
14
14
|
var COOKIE = 'fabric_button';
|
|
15
15
|
var GET_FABRIC = 'https://passioncode.ai/fabric';
|
|
16
16
|
var ABSENT_AFTER_MS = 1500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.3 · 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
|
|
@@ -115,7 +115,7 @@ html.fd-js .fd-chrome { position: sticky; top: var(--fd-chrome-top, 0px); z-inde
|
|
|
115
115
|
text-decoration: none; white-space: nowrap; cursor: pointer;
|
|
116
116
|
transition: background-color var(--dur-hover) var(--motion-ease), color var(--dur-hover) var(--motion-ease); }
|
|
117
117
|
.fd-nav a:hover, .fd-more > summary:hover { background: var(--panel-2); color: var(--ink); }
|
|
118
|
-
.fd-nav a[aria-current] { background: var(--accent-weak); color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); }
|
|
118
|
+
.fd-nav a[aria-current]:not([aria-current="false"]) { background: var(--accent-weak); color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); }
|
|
119
119
|
.fd-more { position: relative; flex: none; }
|
|
120
120
|
.fd-more[hidden] { display: none; }
|
|
121
121
|
.fd-more > summary { list-style: none; border: 1px solid var(--edge); }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.3 · 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.3';
|
|
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 */
|
|
@@ -150,6 +150,7 @@
|
|
|
150
150
|
|
|
151
151
|
/* ---- navigation: fold what does not fit into More (ED-3) ---- */
|
|
152
152
|
function foldNav(nav) {
|
|
153
|
+
if (typeof nav.fdRefresh === 'function') { nav.fdRefresh(); return; } // folded already: refit, no second observers
|
|
153
154
|
var list = nav.querySelector('.fd-nav-list');
|
|
154
155
|
if (!list) return;
|
|
155
156
|
nav.classList.add('fd-nav--fold');
|
|
@@ -176,23 +177,53 @@
|
|
|
176
177
|
var summaryEl = more.querySelector('summary');
|
|
177
178
|
var label = nav.getAttribute('data-fd-more-label') || 'More';
|
|
178
179
|
|
|
180
|
+
// An item that sticks out by a fraction of a pixel is cut but leaves scrollWidth (rounded) unchanged: compare the
|
|
181
|
+
// last item's edge with the list's, on the side the text runs to.
|
|
182
|
+
var overflows = function () {
|
|
183
|
+
if (list.scrollWidth > list.clientWidth + 1) return true;
|
|
184
|
+
var last = list.lastElementChild;
|
|
185
|
+
if (!last) return false;
|
|
186
|
+
var a = last.getBoundingClientRect(), b = list.getBoundingClientRect();
|
|
187
|
+
return root.getComputedStyle(list).direction === 'rtl' ? a.left < b.left - 0.5 : a.right > b.right + 0.5;
|
|
188
|
+
};
|
|
189
|
+
function summarize() {
|
|
190
|
+
var current = menuList.querySelector('[aria-current]:not([aria-current="false"])');
|
|
191
|
+
summaryEl.textContent = current ? label + ': ' + current.textContent.trim() : label + ' (' + menuList.children.length + ')';
|
|
192
|
+
}
|
|
179
193
|
function layout() {
|
|
194
|
+
// Moving a focused link out of the document loses focus: keep it on the same link across the refit.
|
|
195
|
+
var focused = doc.activeElement && nav.contains(doc.activeElement) ? doc.activeElement : null;
|
|
196
|
+
fit();
|
|
197
|
+
if (focused && focused.isConnected && doc.activeElement !== focused) focused.focus({ preventScroll: true });
|
|
198
|
+
}
|
|
199
|
+
function fit() {
|
|
180
200
|
// Put every item back in its place, then move the last ones out until the rest fit.
|
|
181
201
|
while (menuList.firstChild) list.appendChild(menuList.firstChild);
|
|
182
202
|
more.hidden = true;
|
|
183
|
-
if (
|
|
203
|
+
if (!overflows()) { summaryEl.textContent = label; return; }
|
|
184
204
|
more.hidden = false;
|
|
185
205
|
var items = list.children;
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
// The summary names the current section or counts the folded ones, and its text takes room from the list, so
|
|
207
|
+
// set it after every move and measure again with it in place (a longer summary left a half-cut item, FAA-104).
|
|
208
|
+
summarize();
|
|
209
|
+
while (items.length && overflows()) {
|
|
210
|
+
menuList.insertBefore(items[items.length > 1 ? items.length - 1 : 0], menuList.firstChild);
|
|
211
|
+
summarize();
|
|
188
212
|
}
|
|
189
|
-
if (list.scrollWidth > list.clientWidth + 1 && items.length) menuList.insertBefore(items[0], menuList.firstChild);
|
|
190
|
-
var current = menuList.querySelector('[aria-current]');
|
|
191
|
-
summaryEl.textContent = current ? label + ': ' + current.textContent.trim() : label + ' (' + menuList.children.length + ')';
|
|
192
213
|
}
|
|
193
214
|
layout();
|
|
194
215
|
if (typeof root.ResizeObserver === 'function') new root.ResizeObserver(function () { layout(); }).observe(nav);
|
|
195
216
|
else root.addEventListener('resize', layout);
|
|
217
|
+
// A page that moves aria-current (its route changed) gets a fresh summary and fit, without telling the kit.
|
|
218
|
+
if (typeof root.MutationObserver === 'function') {
|
|
219
|
+
new root.MutationObserver(layout).observe(nav, { subtree: true, attributes: true, attributeFilter: ['aria-current'] });
|
|
220
|
+
}
|
|
221
|
+
nav.fdRefresh = layout;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* A page can also ask for a new fit itself, for example after it changed the items' text. */
|
|
225
|
+
function refreshNav(nav) {
|
|
226
|
+
if (nav && typeof nav.fdRefresh === 'function') nav.fdRefresh();
|
|
196
227
|
}
|
|
197
228
|
|
|
198
229
|
/* ---- wide boxes: keyboard-reachable, with a name, marked when they overflow (ED-4) ---- */
|
|
@@ -247,6 +278,7 @@
|
|
|
247
278
|
api.applyAppearance = applyAppearance;
|
|
248
279
|
api.prepareScrollBox = prepareScrollBox;
|
|
249
280
|
api.foldNav = foldNav;
|
|
281
|
+
api.refreshNav = refreshNav;
|
|
250
282
|
// Apply the theme before first paint when loaded without defer; the rest waits for the DOM.
|
|
251
283
|
applyAppearance();
|
|
252
284
|
if (doc.readyState === 'loading') doc.addEventListener('DOMContentLoaded', init); else init();
|
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.3",
|
|
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": "fdcc7dadea987f0b89c63a5460b3b2b2c870768decc9ee981824a0dc0095169e",
|
|
19
|
+
"fabric-dashboard.js": "a69f80211132bb36c7a8d297d89674f0fafc087121289abf8cbebb6034e03235",
|
|
20
|
+
"fabric-button.js": "7f35ff22226e2c57e6ba980424fc839207ad150d1f235043296f9ac0fb5425a1",
|
|
21
21
|
"themes.json": "511839f1a1a83eb37fadfd132791474497d5c28c5091700b9aa31ad076e359b5"
|
|
22
22
|
},
|
|
23
23
|
"history": {
|
|
@@ -39,6 +39,11 @@
|
|
|
39
39
|
"fabric-dashboard.css": "fb8ed17166cb52cf5af1b28b5783fc069d3d673fe50d291a9d900154b6730d98",
|
|
40
40
|
"fabric-dashboard.js": "55fcfe9340877e718728eb7430c6cdc9453248315bda5594602e2713eddc3db1",
|
|
41
41
|
"fabric-button.js": "9f76e604140c8f7d3f97c21530c601d652348639403a1721c0c7fb8abe9b9209"
|
|
42
|
+
},
|
|
43
|
+
"1.1.3": {
|
|
44
|
+
"fabric-dashboard.css": "fdcc7dadea987f0b89c63a5460b3b2b2c870768decc9ee981824a0dc0095169e",
|
|
45
|
+
"fabric-dashboard.js": "a69f80211132bb36c7a8d297d89674f0fafc087121289abf8cbebb6034e03235",
|
|
46
|
+
"fabric-button.js": "7f35ff22226e2c57e6ba980424fc839207ad150d1f235043296f9ac0fb5425a1"
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
49
|
}
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md
CHANGED
|
@@ -59,6 +59,7 @@ Never edit the copied files: the page's own rules go in its own stylesheet, cons
|
|
|
59
59
|
| Grids | `.fd-grid` (cards, 320 px columns), `.fd-grid--tiles` (160 px), `.fd-grid--wide` (480 px); `--fd-col` sets your own |
|
|
60
60
|
| Wide content | `<div class="fd-scroll" data-fd-label="Jobs table"><table class="fd-table">…</table></div>`, `<pre class="fd-scroll">` |
|
|
61
61
|
| Atoms | `.fd-card`, `.fd-tile`, `.fd-chip` + `.fd-dot` + `.fd-s-ok\|warn\|danger\|info`, `.fd-btn`, `.fd-btn--primary`, `.fd-input`, `.fd-select`, `.fd-banner`, `.fd-empty`, `.fd-pairs` |
|
|
62
|
+
| Navigation that folds | with the script, links that do not fit move into **More** (`data-fd-more-label` names it, `data-fd-no-fold` keeps a nav as is); the summary names the current section (`aria-current`) or counts the folded links, and the fit is measured with that text in place. Moving `aria-current` refits on its own; after changing the links' text call `FabricDashboard.refreshNav(nav)` (since 1.1.3) |
|
|
62
63
|
| Own appearance controls | `<select data-fd-theme-picker>`, `<select data-fd-scheme-picker>` (the script fills them; hidden while the host owns appearance) |
|
|
63
64
|
|
|
64
65
|
Tokens are the workbench layer (`--bg`, `--panel`, `--panel-2`, `--ink`, `--muted`, `--border`,
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md
CHANGED
|
@@ -90,7 +90,8 @@ DL-19: an MCP tool answers `refusal_tool_result(r)` / `refusalToolResult(r)`: `i
|
|
|
90
90
|
`structuredContent: {error: {code, message, data: {detail}}}`; an HTTP route answers `refusal_http(r)` /
|
|
91
91
|
`refusalHttp(r)` with the code's status (401 for `unauthenticated`, `token-expired`, `principal-unproven`, with
|
|
92
92
|
`WWW-Authenticate: Bearer error="invalid_token"`; 503 for `issuer-unavailable` and `unknown-state`; 403 for the
|
|
93
|
-
rest
|
|
93
|
+
rest, `profile-forbids` included: DEC-0106's refusal of a call between two machines of one estate that a machine's
|
|
94
|
+
profile does not allow). A published key the service cannot use (of small order, for another use, or published twice) is the
|
|
94
95
|
issuer's fault, `issuer-unavailable` (DEC-0045); a gate without a trusted issuer refuses everything as
|
|
95
96
|
`no-trusted-issuer`. `detail` is a short machine word; the token, the approval and the keys never appear in a result or a log.
|
|
96
97
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/estate-record.md
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Fabric Agent Contract DEC-0055, `docs/specification/estate-record.md`, schema `schemas/estate-record.schema.json`,
|
|
4
4
|
rules `FAC-SEM-072…076`, with contexts (DEC-0082, `docs/specification/contexts.md`, `FAC-SEM-110`, `FAC-SEM-111`) and a
|
|
5
|
-
partner's scoped publisher key (DEC-0090, `docs/specification/partner-channel.md`, `FAC-SEM-122`)
|
|
5
|
+
partner's scoped publisher key (DEC-0090, `docs/specification/partner-channel.md`, `FAC-SEM-122`) and each machine's
|
|
6
|
+
profile (DEC-0106, `docs/specification/machine-calls.md`, `FAC-SEM-134`).
|
|
6
7
|
One revision of one person's estate lists:
|
|
7
8
|
- the passkeys that sign it;
|
|
8
|
-
- the machines, with their device keys
|
|
9
|
+
- the machines, with their device keys, a certificate of each machine's hub key and, optionally, a profile;
|
|
9
10
|
- the packages placed on each machine, each in a context: the person's own, or an organization's;
|
|
10
11
|
- where each secret slot is filled from (by reference only);
|
|
11
12
|
- share grants and revocations.
|
|
@@ -19,6 +20,7 @@ derived from its own digest. Python: [`scripts/fabric_estate.py`](../scripts/fab
|
|
|
19
20
|
- Applying a revision
|
|
20
21
|
- Trusting a delegation key
|
|
21
22
|
- Contexts: one agent for you and for an organization
|
|
23
|
+
- Machine profiles: full, member, view
|
|
22
24
|
- The estate ceremonies
|
|
23
25
|
- Share grants into an organization
|
|
24
26
|
- Checking a record you produce
|
|
@@ -57,7 +59,7 @@ It checks, in the order of the ER table:
|
|
|
57
59
|
7. **The window.** At most 30 days. A revision may be issued up to 60 s ahead of the verifier's clock (DEC-0066,
|
|
58
60
|
`CLOCK_SKEW_SECONDS`); earlier than that it is `not-yet-valid`.
|
|
59
61
|
8. **The record's own rules.** A violation is `rule-violation` with its `codes`, `FAC-SEM-072…076`, `FAC-SEM-110`,
|
|
60
|
-
`FAC-SEM-111`, `FAC-SEM-122` and `FAC-SEM-092`
|
|
62
|
+
`FAC-SEM-111`, `FAC-SEM-122`, `FAC-SEM-134` and `FAC-SEM-092`
|
|
61
63
|
(each passkey the record lists is a signing credential, its origins within its RP ID).
|
|
62
64
|
|
|
63
65
|
Dates are strict RFC 3339: a `T`, an offset, and a day that exists. `:60` and a space are refused. Passkey JWK `x`
|
|
@@ -128,6 +130,36 @@ Every rule is total on hostile JSON, as the contract's are: an `instancePath` na
|
|
|
128
130
|
non-object before it does not shift it), and a value whose own `toString` member is data is shown as its JSON. Both kits
|
|
129
131
|
answer the contract's contexts fixtures and variants of them (`test/fixtures/contract/estate-vectors.json`).
|
|
130
132
|
|
|
133
|
+
## Machine profiles: full, member, view
|
|
134
|
+
|
|
135
|
+
DEC-0106 gives a machine an optional `profile`. It says what the machine may be when other machines of the estate call
|
|
136
|
+
it over the relay.
|
|
137
|
+
|
|
138
|
+
- **`full`**, the default. A record omits it: a machine with no `profile` is `full`. Only a `full` machine carries a
|
|
139
|
+
`hubKey`.
|
|
140
|
+
- **`member`** takes calls from the estate's machines and holds only the secret slots the record places on it. It has
|
|
141
|
+
no `hubKey`.
|
|
142
|
+
- **`view`** only reads. It has no `hubKey`, no placement and no secret placement, and no secret placement names it as
|
|
143
|
+
`from`.
|
|
144
|
+
|
|
145
|
+
`FAC-SEM-134` checks all of it: an unknown value, a hub key on a `member` or `view` machine, and a `view` machine that
|
|
146
|
+
places, holds or fills a secret. A revision that breaks it is `rule-violation`. A profile changes only by a revision
|
|
147
|
+
the passkey signs.
|
|
148
|
+
|
|
149
|
+
`machine_profile(record, machine_id)` / `machineProfile(record, machineId)` answers a machine's profile: `full` for a
|
|
150
|
+
machine listed once with no `profile`, its value when it is one of the three, and `None` / `undefined` otherwise (not
|
|
151
|
+
listed, listed twice, an unreadable record or id, an unknown value). It never raises. Both kits answer the contract's
|
|
152
|
+
own profile vectors (`fixtures/vectors/machine-call.json`) and hostile inputs (`test/fixtures/contract/estate-vectors.json`).
|
|
153
|
+
|
|
154
|
+
- **Update a copied kit before a record carries `profile`.** A copy older than 0.47.0 refuses a record with `profile`
|
|
155
|
+
only when it checks the schema; its rules find nothing broken on a `view` machine that places agents. Fabric writes
|
|
156
|
+
`profile` only once every reader of its records is pinned at or after DEC-0106, the kits included:
|
|
157
|
+
`fabric_kit.py install <dir> --module fabric_estate` (or `--lang node --module fabric-estate`).
|
|
158
|
+
- **The kit does not take calls between machines.** Placing a relay caller (`relayCallerTier`), judging a call by
|
|
159
|
+
profile (`machineCallVerdict`) and sealing it (`fabric-agent-call/1`, HPKE) are a relay node's duties; no kit-built
|
|
160
|
+
service is one yet (FAA-106). A delegation verifier still names the refusal: `profile-forbids` is a DL-19 code
|
|
161
|
+
([delegation](delegation.md)).
|
|
162
|
+
|
|
131
163
|
## The estate ceremonies
|
|
132
164
|
|
|
133
165
|
Contract DEC-0084: create a network, add a machine nearby (a six-digit comparison code) or headless (an enroll token),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# fabric-service/0.1: wire reference
|
|
2
2
|
|
|
3
|
-
Pinned to `fabric-agent-contract` commit `
|
|
3
|
+
Pinned to `fabric-agent-contract` commit `87d384ffce2757081b7ab227e5dad3dddd08328f`
|
|
4
4
|
(`docs/specification/service.md`, DEC-0015; the usage report DEC-0021; Windows and Linux supervision
|
|
5
5
|
DEC-0032 and DEC-0033; the operator channel DEC-0034 and DEC-0035; the embedded dashboard DEC-0036;
|
|
6
6
|
delegation and the operator session's lifetime DEC-0039; the meter's call window DEC-0041; session handoff DEC-0042;
|
|
@@ -11,7 +11,8 @@ estate record's 60 s skew DEC-0066; an app's own descriptor DEC-0069; the descri
|
|
|
11
11
|
by normal form DEC-0076; the project board's directory page DEC-0077 and a replacement's transferred attempts DEC-0078; an operator's hold DEC-0079, a structured finding DEC-0080 and the owner's settlement DEC-0081; `fabric-connections/0.1` in the protocol register
|
|
12
12
|
DEC-0096; a schema pattern never uses a bare dot DEC-0097; the board as Fabric 0.3.9 serves it DEC-0098 and DEC-0102, a
|
|
13
13
|
`processor-hosted` peer DEC-0099, three device protocols in the register DEC-0101; a call queue's `queue-full` and
|
|
14
|
-
the `agent-directory`, `fabric-load` and `service-load` protocols DEC-0104
|
|
14
|
+
the `agent-directory`, `fabric-load` and `service-load` protocols DEC-0104; a machine's `profile` in the estate record,
|
|
15
|
+
`profile-forbids` and the `fabric-agent-call` protocol DEC-0106). The contract's schemas are normative;
|
|
15
16
|
this page is the working summary. Extension key:
|
|
16
17
|
`https://fabric.passioncode.ai/agent-contract/extensions/service/0.1`.
|
|
17
18
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { atomicWrite } from './fabric-paths.mjs'; // the kit's private writer (F
|
|
|
19
19
|
export const REFUSAL_CODES = Object.freeze([
|
|
20
20
|
'unauthenticated', 'token-expired', 'wrong-audience', 'scope-not-granted', 'effect-above-ceiling', 'no-grant',
|
|
21
21
|
'grant-expired', 'grant-revoked', 'limit-reached', 'approval-required', 'approval-invalid', 'approval-reused',
|
|
22
|
-
'principal-unproven', 'credential-source-refused', 'chain-too-deep', 'issuer-unavailable', 'unknown-state',
|
|
22
|
+
'principal-unproven', 'credential-source-refused', 'chain-too-deep', 'profile-forbids', 'issuer-unavailable', 'unknown-state',
|
|
23
23
|
]);
|
|
24
24
|
export const EFFECT_CLASSES = Object.freeze(['none', 'draft', 'publish', 'send', 'reply', 'charge', 'delete', 'merge', 'deploy', 'change-policy']);
|
|
25
25
|
export const DELEGATION_HEADER = 'Fabric-Delegation';
|
|
@@ -52,6 +52,7 @@ export const REFUSAL_MESSAGES = Object.freeze({
|
|
|
52
52
|
'principal-unproven': "The caller's proof is missing or stale.",
|
|
53
53
|
'credential-source-refused': 'The grant names a credential source that is not allowed.',
|
|
54
54
|
'chain-too-deep': 'The actor chain is deeper than four.',
|
|
55
|
+
'profile-forbids': "The caller's or the target's machine profile does not allow this call.",
|
|
55
56
|
'issuer-unavailable': "The estate's published keys cannot be read.",
|
|
56
57
|
'unknown-state': 'The state cannot be established, so the call is refused.',
|
|
57
58
|
});
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import { ROUTES } from './fabric-usage.mjs';
|
|
|
13
13
|
// document's `extensions`. The kit is assets/dashboard-kit; its version is the one in kit.json.
|
|
14
14
|
export const DASHBOARD_EXTENSION_KEY = 'https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1';
|
|
15
15
|
|
|
16
|
-
export const DASHBOARD_KIT = 'fabric-dashboard-kit@1.1.
|
|
16
|
+
export const DASHBOARD_KIT = 'fabric-dashboard-kit@1.1.3';
|
|
17
17
|
|
|
18
18
|
export const REFERENCE_THEMES = ['graphite', 'fabric', 'paper', 'forest', 'ocean', 'ember', 'contrast'];
|
|
19
19
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
//
|
|
5
5
|
// - verifyEstateRecord(record, { at, parent } | { at, authorities }) — the verdict a machine applies a revision on, after
|
|
6
6
|
// it has checked the revision against estate-record.schema.json (the verifier does not check the schema);
|
|
7
|
-
// - estateRecordRules(kind, value) — FAC-SEM-072…076;
|
|
7
|
+
// - estateRecordRules(kind, value) — FAC-SEM-072…076, with FAC-SEM-134 on each machine's profile (DEC-0106);
|
|
8
|
+
// - machineProfile(record, machineId) — a machine's profile (DEC-0106): `full`, `member`, `view`, or undefined;
|
|
8
9
|
// - hubKeyCertified(record, kid, x, at) — DL-14: a delegation verifier that reads the estate record trusts a token's
|
|
9
10
|
// `kid` only while a current revision certifies it for a machine (fabric-delegation.mjs calls it).
|
|
10
11
|
//
|
|
@@ -540,6 +541,50 @@ function placementGrants(value, flag) {
|
|
|
540
541
|
});
|
|
541
542
|
}
|
|
542
543
|
|
|
544
|
+
/** DEC-0106: what a machine of the estate may be. Absent is `full`, and a writer omits `full`. */
|
|
545
|
+
export const MACHINE_PROFILES = Object.freeze(['full', 'member', 'view']);
|
|
546
|
+
const isProfile = (value) => typeof value === 'string' && MACHINE_PROFILES.includes(value);
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* A machine's profile in a record (DEC-0106): `full` when the machine is listed once with no `profile`, its value when
|
|
550
|
+
* that is one of the three, undefined otherwise (not listed, listed twice, an unreadable record or id, an unknown
|
|
551
|
+
* value). The contract's machineProfile; it never throws.
|
|
552
|
+
*/
|
|
553
|
+
export function machineProfile(record, machineId) {
|
|
554
|
+
if (!isObject(record) || !isString(machineId)) return undefined;
|
|
555
|
+
const found = list(record.machines).filter((machine) => machine.id === machineId);
|
|
556
|
+
if (found.length !== 1) return undefined;
|
|
557
|
+
const { profile } = found[0];
|
|
558
|
+
if (profile === undefined) return 'full';
|
|
559
|
+
return isProfile(profile) ? profile : undefined;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* FAC-SEM-134 (DEC-0106): a profile, when present, is `full`, `member` or `view`; only a `full` machine carries a
|
|
564
|
+
* `hubKey`; a `view` machine has no placement and no secret placement, and no secret placement names it as `from`.
|
|
565
|
+
*/
|
|
566
|
+
function machineProfiles(value, flag) {
|
|
567
|
+
const views = new Set();
|
|
568
|
+
indexed(value.machines).forEach(([machine, m]) => {
|
|
569
|
+
if (machine.profile === undefined) return;
|
|
570
|
+
if (!isProfile(machine.profile)) {
|
|
571
|
+
flag(`/machines/${m}/profile`, `profile ${show(machine.profile)} is none of full, member, view`);
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (machine.profile !== 'full' && machine.hubKey !== undefined) flag(`/machines/${m}/hubKey`, `a ${machine.profile} machine is never the hub's: only a full machine carries a hub key`);
|
|
575
|
+
if (machine.profile === 'view') {
|
|
576
|
+
views.add(machine.id);
|
|
577
|
+
if (list(machine.packages).length > 0) flag(`/machines/${m}/packages`, 'a view machine runs no agent: it has no placement');
|
|
578
|
+
if (list(machine.secrets).length > 0) flag(`/machines/${m}/secrets`, "a view machine holds none of the estate's secrets");
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
indexed(value.machines).forEach(([machine, m]) => {
|
|
582
|
+
indexed(machine.secrets).forEach(([secret, s]) => {
|
|
583
|
+
if (views.has(secret.from)) flag(`/machines/${m}/secrets/${s}/from`, `machine ${show(secret.from)} is a view machine: it is the source of no secret`);
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
543
588
|
function recordFindings(value) {
|
|
544
589
|
const findings = [];
|
|
545
590
|
revisionWhole(value, flagger(findings, 'FAC-SEM-072'));
|
|
@@ -550,6 +595,7 @@ function recordFindings(value) {
|
|
|
550
595
|
grantsAndRevocations(value, flagger(findings, 'FAC-SEM-076'));
|
|
551
596
|
indexed(value.shareGrants).forEach(([grant, index]) => findings.push(...grantContextFindings(grant, `/shareGrants/${index}`)));
|
|
552
597
|
placementGrants(value, flagger(findings, 'FAC-SEM-111'));
|
|
598
|
+
machineProfiles(value, flagger(findings, 'FAC-SEM-134'));
|
|
553
599
|
// FAC-SEM-092 (DEC-0063) on each passkey the record lists.
|
|
554
600
|
indexed(value.authorities).forEach(([authority, index]) => signingCredential(authority, `/authorities/${index}`, flagger(findings, 'FAC-SEM-092')));
|
|
555
601
|
return findings;
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { credentialName, secretArgument, secretUrl, secretValue } from './fabric
|
|
|
8
8
|
/** Each contract protocol's published revisions, oldest first (the contract's `PROTOCOL_REVISIONS`); a test holds it equal to the contract's. */
|
|
9
9
|
export const PROTOCOL_REVISIONS = new Map(Object.entries({
|
|
10
10
|
'access-log': ['1'], approval: ['1'], 'activity-summary': ['1'], 'agent-directory': ['1'], 'coding-agents': ['1'], 'enroll-token': ['1'], entitlement: ['1'], 'entitlement-key-set': ['1'], 'estate-record': ['1'], 'execution-packet': ['1'],
|
|
11
|
-
'fabric-activity': ['0.1'], 'fabric-connections': ['0.1'], 'fabric-load': ['0.1'], 'fabric-dashboard': ['0.1'], 'fabric-delegation': ['0.1'], 'fabric-device': ['0.1'],
|
|
11
|
+
'fabric-activity': ['0.1'], 'fabric-agent-call': ['1'], 'fabric-connections': ['0.1'], 'fabric-load': ['0.1'], 'fabric-dashboard': ['0.1'], 'fabric-delegation': ['0.1'], 'fabric-device': ['0.1'],
|
|
12
12
|
'fabric-interop': ['0.1', '0.2'], 'fabric-local-channel': ['0.1'], 'fabric-local-runner': ['0.1'], 'fabric-operator-channel': ['0.1'],
|
|
13
13
|
'fabric-package': ['1'], 'fabric-project-comms': ['0.1'], 'fabric-proposal': ['1'], 'fabric-provider': ['0.1'], 'fabric-relay': ['0.1'],
|
|
14
14
|
'fabric-secret-envelope': ['1'], 'fabric-service': ['0.1'], 'fabric-settings-backup': ['1'], heartbeat: ['1'], 'learning-note': ['1'],
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py
CHANGED
|
@@ -49,7 +49,8 @@ from fabric_paths import atomic_write as _atomic_write # noqa: E402 - the kit's
|
|
|
49
49
|
REFUSAL_CODES = (
|
|
50
50
|
"unauthenticated", "token-expired", "wrong-audience", "scope-not-granted", "effect-above-ceiling", "no-grant",
|
|
51
51
|
"grant-expired", "grant-revoked", "limit-reached", "approval-required", "approval-invalid", "approval-reused",
|
|
52
|
-
"principal-unproven", "credential-source-refused", "chain-too-deep", "
|
|
52
|
+
"principal-unproven", "credential-source-refused", "chain-too-deep", "profile-forbids", "issuer-unavailable",
|
|
53
|
+
"unknown-state",
|
|
53
54
|
)
|
|
54
55
|
EFFECT_CLASSES = ("none", "draft", "publish", "send", "reply", "charge", "delete", "merge", "deploy", "change-policy")
|
|
55
56
|
DELEGATION_HEADER = "Fabric-Delegation"
|
|
@@ -88,6 +89,7 @@ REFUSAL_MESSAGES = {
|
|
|
88
89
|
"principal-unproven": "The caller's proof is missing or stale.",
|
|
89
90
|
"credential-source-refused": "The grant names a credential source that is not allowed.",
|
|
90
91
|
"chain-too-deep": "The actor chain is deeper than four.",
|
|
92
|
+
"profile-forbids": "The caller's or the target's machine profile does not allow this call.",
|
|
91
93
|
"issuer-unavailable": "The estate's published keys cannot be read.",
|
|
92
94
|
"unknown-state": "The state cannot be established, so the call is refused.",
|
|
93
95
|
}
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py
CHANGED
|
@@ -46,7 +46,7 @@ from fabric_usage import (
|
|
|
46
46
|
DASHBOARD_EXTENSION_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1"
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
DASHBOARD_KIT = "fabric-dashboard-kit@1.1.
|
|
49
|
+
DASHBOARD_KIT = "fabric-dashboard-kit@1.1.3"
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
REFERENCE_THEMES = ("graphite", "fabric", "paper", "forest", "ocean", "ember", "contrast")
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py
CHANGED
|
@@ -10,7 +10,8 @@ at the pin, ported answer for answer and held to the contract's own vectors (`te
|
|
|
10
10
|
- ``verify_estate_record(record, at=..., parent=... | authorities=...)`` — the verdict a machine applies a revision on,
|
|
11
11
|
after it has checked the revision against `estate-record.schema.json` (the verifier does not check the schema);
|
|
12
12
|
- ``estate_record_rules(kind, value)`` — FAC-SEM-072…076 for `estate-record`, `estate-record-revision` and
|
|
13
|
-
`estate-placement
|
|
13
|
+
`estate-placement`, with FAC-SEM-134 on each machine's profile (DEC-0106);
|
|
14
|
+
- ``machine_profile(record, machine_id)`` — a machine's profile (DEC-0106): `full`, `member`, `view`, or None;
|
|
14
15
|
- ``hub_key_certified(record, kid, x, at)`` — DL-14: a delegation verifier that reads the estate record trusts a token's
|
|
15
16
|
`kid` only while a current revision certifies it for a machine (``fabric_delegation`` calls it).
|
|
16
17
|
|
|
@@ -645,6 +646,54 @@ def _secret_references(value: Dict[str, Any], flag) -> None:
|
|
|
645
646
|
slots.append(key)
|
|
646
647
|
|
|
647
648
|
|
|
649
|
+
#: DEC-0106: what a machine of the estate may be. Absent is `full`, and a writer omits `full`.
|
|
650
|
+
MACHINE_PROFILES = ("full", "member", "view")
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
def _is_profile(value: Any) -> bool:
|
|
654
|
+
return isinstance(value, str) and value in MACHINE_PROFILES
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def machine_profile(record: Any, machine_id: Any) -> Optional[str]:
|
|
658
|
+
"""A machine's profile in a record (DEC-0106): ``full`` when the machine is listed once with no ``profile``, its value
|
|
659
|
+
when that is one of the three, None otherwise (not listed, listed twice, an unreadable record or id, an unknown
|
|
660
|
+
value). The contract's ``machineProfile``; never raises."""
|
|
661
|
+
if not isinstance(record, dict) or not isinstance(machine_id, str):
|
|
662
|
+
return None
|
|
663
|
+
found = [m for m in _list(_get(record, "machines")) if _same(_get(m, "id"), machine_id)]
|
|
664
|
+
if len(found) != 1:
|
|
665
|
+
return None
|
|
666
|
+
profile = _get(found[0], "profile")
|
|
667
|
+
if profile is _MISSING:
|
|
668
|
+
return "full"
|
|
669
|
+
return profile if _is_profile(profile) else None
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
def _machine_profiles(value: Dict[str, Any], flag) -> None:
|
|
673
|
+
"""FAC-SEM-134 (DEC-0106): a profile, when present, is `full`, `member` or `view`; only a `full` machine carries a
|
|
674
|
+
`hubKey`; a `view` machine has no placement and no secret placement, and no secret placement names it as `from`."""
|
|
675
|
+
views: List[Any] = []
|
|
676
|
+
for machine, m in _indexed(_get(value, "machines")):
|
|
677
|
+
profile = _get(machine, "profile")
|
|
678
|
+
if profile is _MISSING:
|
|
679
|
+
continue
|
|
680
|
+
if not _is_profile(profile):
|
|
681
|
+
flag("/machines/%d/profile" % m, "profile %s is none of full, member, view" % _show(profile))
|
|
682
|
+
continue
|
|
683
|
+
if profile != "full" and _get(machine, "hubKey") is not _MISSING:
|
|
684
|
+
flag("/machines/%d/hubKey" % m, "a %s machine is never the hub's: only a full machine carries a hub key" % profile)
|
|
685
|
+
if profile == "view":
|
|
686
|
+
views.append(_get(machine, "id"))
|
|
687
|
+
if _list(_get(machine, "packages")):
|
|
688
|
+
flag("/machines/%d/packages" % m, "a view machine runs no agent: it has no placement")
|
|
689
|
+
if _list(_get(machine, "secrets")):
|
|
690
|
+
flag("/machines/%d/secrets" % m, "a view machine holds none of the estate's secrets")
|
|
691
|
+
for machine, m in _indexed(_get(value, "machines")):
|
|
692
|
+
for secret, s in _indexed(_get(machine, "secrets")):
|
|
693
|
+
if _contains(views, _get(secret, "from")):
|
|
694
|
+
flag("/machines/%d/secrets/%d/from" % (m, s), "machine %s is a view machine: it is the source of no secret" % _show(_get(secret, "from")))
|
|
695
|
+
|
|
696
|
+
|
|
648
697
|
def _grant_key(ident: Any) -> Any:
|
|
649
698
|
"""A grant's id is a URI, so grants and their revocations are keyed by its normal form (DEC-0076)."""
|
|
650
699
|
import fabric_identifiers # noqa: E402 - beside this file
|
|
@@ -783,6 +832,7 @@ def _record_findings(value: Dict[str, Any]) -> List[Dict[str, str]]:
|
|
|
783
832
|
for grant, index in _indexed(_get(value, "shareGrants")): # FAC-SEM-110 (DEC-0082)
|
|
784
833
|
findings.extend(grant_context_findings(grant, "/shareGrants/%d" % index))
|
|
785
834
|
_placement_grants(value, _finding(findings, "FAC-SEM-111"))
|
|
835
|
+
_machine_profiles(value, _finding(findings, "FAC-SEM-134"))
|
|
786
836
|
for authority, index in _indexed(_get(value, "authorities")): # FAC-SEM-092 (DEC-0063)
|
|
787
837
|
_signing_credential(authority, "/authorities/%d" % index, _finding(findings, "FAC-SEM-092"))
|
|
788
838
|
return findings
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py
CHANGED
|
@@ -15,7 +15,7 @@ if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from
|
|
|
15
15
|
PROTOCOL_REVISIONS: Dict[str, Tuple[str, ...]] = {
|
|
16
16
|
"access-log": ("1",), "approval": ("1",), "activity-summary": ("1",), "agent-directory": ("1",), "coding-agents": ("1",), "enroll-token": ("1",), "entitlement": ("1",),
|
|
17
17
|
"entitlement-key-set": ("1",), "estate-record": ("1",), "execution-packet": ("1",),
|
|
18
|
-
"fabric-activity": ("0.1",), "fabric-connections": ("0.1",), "fabric-load": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
18
|
+
"fabric-activity": ("0.1",), "fabric-agent-call": ("1",), "fabric-connections": ("0.1",), "fabric-load": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
19
19
|
"fabric-interop": ("0.1", "0.2"), "fabric-local-channel": ("0.1",), "fabric-local-runner": ("0.1",),
|
|
20
20
|
"fabric-operator-channel": ("0.1",), "fabric-package": ("1",), "fabric-project-comms": ("0.1",), "fabric-proposal": ("1",),
|
|
21
21
|
"fabric-provider": ("0.1",), "fabric-relay": ("0.1",), "fabric-secret-envelope": ("1",), "fabric-service": ("0.1",),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabric-service-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"about": "The service kit's modules in dependency order: a module imports only modules listed before it. Written by fabric_kit.py build; edit the order and layers by hand, never the digests.",
|
|
5
5
|
"python": [
|
|
6
6
|
{
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"fabric_secrets",
|
|
78
78
|
"fabric_time"
|
|
79
79
|
],
|
|
80
|
-
"sha256": "
|
|
80
|
+
"sha256": "a7400a3b2498ea2b6e3a845ed438580f2bf3c4ce58854ba4ad22d7cdf6f846bc"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
"module": "fabric_delegation",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"fabric_jsvalue",
|
|
90
90
|
"fabric_paths"
|
|
91
91
|
],
|
|
92
|
-
"sha256": "
|
|
92
|
+
"sha256": "6638a6039befe3b43f59018bab292e050931af21b544df1044cd5059572ded36"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"module": "fabric_share",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"imports": [
|
|
151
151
|
"fabric_secrets"
|
|
152
152
|
],
|
|
153
|
-
"sha256": "
|
|
153
|
+
"sha256": "89babdb43468a90e4aa9df388a82dd498ae1e0ac5445ac4a1b9c225d8bc61f67"
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
"module": "fabric_connections",
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
"fabric_secrets",
|
|
210
210
|
"fabric_usage"
|
|
211
211
|
],
|
|
212
|
-
"sha256": "
|
|
212
|
+
"sha256": "daf16f95b1810283b1386488e006e940a0cdfa5c3c8d09386ac33d29d58df78d"
|
|
213
213
|
},
|
|
214
214
|
{
|
|
215
215
|
"module": "fabric_auth",
|
|
@@ -473,7 +473,7 @@
|
|
|
473
473
|
"fabric-secrets",
|
|
474
474
|
"fabric-time"
|
|
475
475
|
],
|
|
476
|
-
"sha256": "
|
|
476
|
+
"sha256": "c4784b0f73d06baaa5f8d104eb33ec21bf5433abfbaed046f24f1d07cf78c782"
|
|
477
477
|
},
|
|
478
478
|
{
|
|
479
479
|
"module": "fabric-delegation",
|
|
@@ -485,7 +485,7 @@
|
|
|
485
485
|
"fabric-jsvalue",
|
|
486
486
|
"fabric-paths"
|
|
487
487
|
],
|
|
488
|
-
"sha256": "
|
|
488
|
+
"sha256": "dafde9ea327c88d92dc73d1400282b43dc6f84dd345a2d2b9b154304f65fc9d7"
|
|
489
489
|
},
|
|
490
490
|
{
|
|
491
491
|
"module": "fabric-share",
|
|
@@ -544,7 +544,7 @@
|
|
|
544
544
|
"imports": [
|
|
545
545
|
"fabric-secrets"
|
|
546
546
|
],
|
|
547
|
-
"sha256": "
|
|
547
|
+
"sha256": "b1fcf14ef1e4f2215111d9fdc89ff5bda3ce2a49aefcd2788feb5a1c12463cbf"
|
|
548
548
|
},
|
|
549
549
|
{
|
|
550
550
|
"module": "fabric-connections",
|
|
@@ -604,7 +604,7 @@
|
|
|
604
604
|
"fabric-secrets",
|
|
605
605
|
"fabric-usage"
|
|
606
606
|
],
|
|
607
|
-
"sha256": "
|
|
607
|
+
"sha256": "95c0b7ff36c29d7c748f1fa6fb1767d6fe8c97fca7f1ee404559930abbd3cc84"
|
|
608
608
|
},
|
|
609
609
|
{
|
|
610
610
|
"module": "fabric-auth",
|
|
@@ -2343,6 +2343,158 @@
|
|
|
2343
2343
|
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2344
2344
|
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2345
2345
|
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
2346
|
+
},
|
|
2347
|
+
"0.46.1": {
|
|
2348
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
2349
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
2350
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
2351
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
2352
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
2353
|
+
"fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
|
|
2354
|
+
"fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
|
|
2355
|
+
"fabric_paths.py": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23",
|
|
2356
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
2357
|
+
"fabric_delegation.py": "4eb5004188fdc6f5c0fd21fb0f9f1f538899a0383bcde0365dea080ef8347182",
|
|
2358
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
2359
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
2360
|
+
"fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
|
|
2361
|
+
"fabric_package.py": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c",
|
|
2362
|
+
"fabric_protocols.py": "420e83dedeccfc93306870b2776908336c81cb349abb188d4cd7be9c8cef9802",
|
|
2363
|
+
"fabric_connections.py": "77d3ccf863c70e9209d21ef45c46a6db9c06237019bc20d54f8d3946873f3f11",
|
|
2364
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
2365
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
2366
|
+
"fabric_backups.py": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb",
|
|
2367
|
+
"fabric_descriptor.py": "daf16f95b1810283b1386488e006e940a0cdfa5c3c8d09386ac33d29d58df78d",
|
|
2368
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
2369
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
2370
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
2371
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
2372
|
+
"fabric_service.py": "d411433ce6ff3e81189b10b2c1a8462335a97cd99574ab0ee7d1c28cf48e1694",
|
|
2373
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
2374
|
+
"fabric_interop_rules.py": "b5f0ecb1791b4c50c5ac151f987f692ed7001bc74841a8a161125ec775145e09",
|
|
2375
|
+
"fabric_interop.py": "f92fa111328fe3811438f733d8f0eb5295e6941c774123a78e26318bdcb35fc3",
|
|
2376
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
2377
|
+
"fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
|
|
2378
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
2379
|
+
"fabric_board_session.py": "2271834c36c23f6bfa50395cd147e6af99f294ef09325fd15f0759ca8e18d941",
|
|
2380
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
2381
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
2382
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
2383
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
2384
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
2385
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
2386
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
2387
|
+
"fabric-secrets.mjs": "6ad8ab18ac899ecc2384e8ec6a3fb689b92be3b9a5ce3a59b92a37d52da5d766",
|
|
2388
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
2389
|
+
"fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
|
|
2390
|
+
"fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
|
|
2391
|
+
"fabric-paths.mjs": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29",
|
|
2392
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
2393
|
+
"fabric-delegation.mjs": "85a7e00e606244e7e02f9cbecc3e421bfcb9c1e12cd2a91daadf8a9c2403104d",
|
|
2394
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
2395
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
2396
|
+
"fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
|
|
2397
|
+
"fabric-package.mjs": "49b757eefcc50e4c91585d5a5694bf3c83d0b03d112c1837f1c9f01466797ab5",
|
|
2398
|
+
"fabric-protocols.mjs": "91a98de17b29e1d100b2e8b965f3310f57b24b65ad6b4596e7a90b26b9069d4d",
|
|
2399
|
+
"fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
|
|
2400
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
2401
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
2402
|
+
"fabric-backups.mjs": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005",
|
|
2403
|
+
"fabric-descriptor.mjs": "95c0b7ff36c29d7c748f1fa6fb1767d6fe8c97fca7f1ee404559930abbd3cc84",
|
|
2404
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
2405
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
2406
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
2407
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
2408
|
+
"fabric-service.mjs": "bc67550e52aa6aa9c6d2ed6cbae52418a3e836623e17164166699f953d8aafa8",
|
|
2409
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
2410
|
+
"fabric-interop-rules.mjs": "57a8081307956e8c381119b361fa5232a7bf791815be8e3541eb5492820e2ea5",
|
|
2411
|
+
"fabric-interop.mjs": "581983ec3e197e5c2340ad25e8468320c69a2459c90097c7fcf2699766b4fb26",
|
|
2412
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
2413
|
+
"fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
|
|
2414
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
2415
|
+
"fabric-board-session.mjs": "e9eefb5d34dc66f6d6b528a9c9e85960fd884e6ea5e179c26cbfe3c054ccf7bc",
|
|
2416
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
2417
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
2418
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
2419
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2420
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2421
|
+
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
2422
|
+
},
|
|
2423
|
+
"0.47.0": {
|
|
2424
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
2425
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
2426
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
2427
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
2428
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
2429
|
+
"fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
|
|
2430
|
+
"fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
|
|
2431
|
+
"fabric_paths.py": "6c92af34292baddf7e10d3134d0a5b0bb23387741812a9f79c409cf1628bad23",
|
|
2432
|
+
"fabric_estate.py": "a7400a3b2498ea2b6e3a845ed438580f2bf3c4ce58854ba4ad22d7cdf6f846bc",
|
|
2433
|
+
"fabric_delegation.py": "6638a6039befe3b43f59018bab292e050931af21b544df1044cd5059572ded36",
|
|
2434
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
2435
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
2436
|
+
"fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
|
|
2437
|
+
"fabric_package.py": "ff533f1b3f92b4ea0f532fcec50b68c610d47549930eef8ad5247692a64dfb3c",
|
|
2438
|
+
"fabric_protocols.py": "89babdb43468a90e4aa9df388a82dd498ae1e0ac5445ac4a1b9c225d8bc61f67",
|
|
2439
|
+
"fabric_connections.py": "77d3ccf863c70e9209d21ef45c46a6db9c06237019bc20d54f8d3946873f3f11",
|
|
2440
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
2441
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
2442
|
+
"fabric_backups.py": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb",
|
|
2443
|
+
"fabric_descriptor.py": "daf16f95b1810283b1386488e006e940a0cdfa5c3c8d09386ac33d29d58df78d",
|
|
2444
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
2445
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
2446
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
2447
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
2448
|
+
"fabric_service.py": "d411433ce6ff3e81189b10b2c1a8462335a97cd99574ab0ee7d1c28cf48e1694",
|
|
2449
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
2450
|
+
"fabric_interop_rules.py": "b5f0ecb1791b4c50c5ac151f987f692ed7001bc74841a8a161125ec775145e09",
|
|
2451
|
+
"fabric_interop.py": "f92fa111328fe3811438f733d8f0eb5295e6941c774123a78e26318bdcb35fc3",
|
|
2452
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
2453
|
+
"fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
|
|
2454
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
2455
|
+
"fabric_board_session.py": "2271834c36c23f6bfa50395cd147e6af99f294ef09325fd15f0759ca8e18d941",
|
|
2456
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
2457
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
2458
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
2459
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
2460
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
2461
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
2462
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
2463
|
+
"fabric-secrets.mjs": "6ad8ab18ac899ecc2384e8ec6a3fb689b92be3b9a5ce3a59b92a37d52da5d766",
|
|
2464
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
2465
|
+
"fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
|
|
2466
|
+
"fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
|
|
2467
|
+
"fabric-paths.mjs": "2201b4ed7126f260931b63e8386377b4317d8dcad419d109bf22c683e44b7f29",
|
|
2468
|
+
"fabric-estate.mjs": "c4784b0f73d06baaa5f8d104eb33ec21bf5433abfbaed046f24f1d07cf78c782",
|
|
2469
|
+
"fabric-delegation.mjs": "dafde9ea327c88d92dc73d1400282b43dc6f84dd345a2d2b9b154304f65fc9d7",
|
|
2470
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
2471
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
2472
|
+
"fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
|
|
2473
|
+
"fabric-package.mjs": "49b757eefcc50e4c91585d5a5694bf3c83d0b03d112c1837f1c9f01466797ab5",
|
|
2474
|
+
"fabric-protocols.mjs": "b1fcf14ef1e4f2215111d9fdc89ff5bda3ce2a49aefcd2788feb5a1c12463cbf",
|
|
2475
|
+
"fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
|
|
2476
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
2477
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
2478
|
+
"fabric-backups.mjs": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005",
|
|
2479
|
+
"fabric-descriptor.mjs": "95c0b7ff36c29d7c748f1fa6fb1767d6fe8c97fca7f1ee404559930abbd3cc84",
|
|
2480
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
2481
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
2482
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
2483
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
2484
|
+
"fabric-service.mjs": "bc67550e52aa6aa9c6d2ed6cbae52418a3e836623e17164166699f953d8aafa8",
|
|
2485
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
2486
|
+
"fabric-interop-rules.mjs": "57a8081307956e8c381119b361fa5232a7bf791815be8e3541eb5492820e2ea5",
|
|
2487
|
+
"fabric-interop.mjs": "581983ec3e197e5c2340ad25e8468320c69a2459c90097c7fcf2699766b4fb26",
|
|
2488
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
2489
|
+
"fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
|
|
2490
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
2491
|
+
"fabric-board-session.mjs": "e9eefb5d34dc66f6d6b528a9c9e85960fd884e6ea5e179c26cbfe3c054ccf7bc",
|
|
2492
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
2493
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
2494
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
2495
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
2496
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
2497
|
+
"share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
|
|
2346
2498
|
}
|
|
2347
2499
|
},
|
|
2348
2500
|
"data": {
|
|
@@ -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. Ships in one plugin with adapting-projects-to-fabric, whose scripts it reuses.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.47.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "87d384ffce2757081b7ab227e5dad3dddd08328f"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Creating Fabric-compatible agents
|
|
@@ -136,7 +136,7 @@ python3 <plugin-dir>/skills/adapting-projects-to-fabric/scripts/adapt_project.py
|
|
|
136
136
|
The effect class is declared, never defaulted: ask the author what the agent does outside itself when the request
|
|
137
137
|
does not say. Cost presets are only for a run whose cost varies; their amounts come from the author or measured runs.
|
|
138
138
|
|
|
139
|
-
Pin exactly contract `0.1.0` at commit `
|
|
139
|
+
Pin exactly contract `0.1.0` at commit `87d384ffce2757081b7ab227e5dad3dddd08328f` and
|
|
140
140
|
read the pinned guide before implementing protocol details. If this skill is installed
|
|
141
141
|
without its sibling, the scaffolder is absent: create the bundle by hand from the pinned
|
|
142
142
|
contract's `docs/guides/connecting-compatible-agents.md` and mark the structural check
|