@passioncode-ai/fabric-agent-adapter 0.83.1 → 0.85.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 +78 -0
- package/README.md +2 -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 +1 -1
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/check_dashboard_link.py +3 -0
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_identifiers.py +1 -0
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_secrets.py +1 -0
- 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 +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +3 -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/references/board.md +8 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +9 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_link.py +3 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a-server.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-actions.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-auth.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-fixture.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-link.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-session.mjs +2 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-shapes.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-slots.mjs +9 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ceremonies.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-connections.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-context.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-crypto.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate-rules.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-events.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-holds.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-hub.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-identifiers.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop-rules.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +6 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-jsvalue.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-load.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-lock.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-logs.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-mandate.mjs +4 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-openrouter.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ops-digest.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package-schema.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-page-links.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-paths.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-peer-owner.mjs +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-platform.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-profiles.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-secrets.mjs +1 -0
- 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 +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-socket-proof.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +15 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-tailnet-identity.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-tailnet.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-time.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-usage.mjs +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_a2a.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_a2a_server.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_actions.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_auth.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_base.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_fixture.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_link.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_session.py +2 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_shapes.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_slots.py +10 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_ceremonies.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_connections.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_context.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_crypto.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate_rules.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_events.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_holds.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_hub.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_identifiers.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +2 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop_rules.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_jsvalue.py +3 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_load.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_lock.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_logs.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_mandate.py +20 -3
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_openrouter.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_ops_digest.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package_schema.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_page_links.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_peer_owner.py +47 -47
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_platform.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_profiles.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_secrets.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_share.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_socket_proof.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +16 -8
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_tailnet.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_tailnet_identity.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_time.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_usage.py +1 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +428 -105
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +2 -1
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/where-agents-run.md +2 -2
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/admit.py +33 -13
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/check_dashboard_link.py +3 -0
- package/plugins/fabric-agent-adapter/skills/observing-products/SKILL.md +1 -1
- 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,83 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.85.0 (2026-11-13)
|
|
4
|
+
|
|
5
|
+
Wave 7 of the backlog sweep of 2026-11-12, part one. The contract pin stays at `93e7db16` (`v0.1.0+2026-11-08.1`).
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **A number subclass is written as the number it stores** (FAA-196 (22)): `js_string`, and so `json_stringify`,
|
|
10
|
+
`key_of` and `fabric_http.json_bytes`, wrote an `int` or `float` subclass through its own `repr`, so
|
|
11
|
+
`json_bytes({'costUsd': numpy.float64(0.25)})` put `np.float64(0.25)` on the wire; it now writes `0.25`.
|
|
12
|
+
- **The core `mandate_covers` reads a call as the board path does** (FAA-196 (21)): the five members the contract reads,
|
|
13
|
+
each once as `call[name]`, so a caller's `__getitem__` override or `defaultdict` default answers on both paths alike,
|
|
14
|
+
never the dict's storage on one of them.
|
|
15
|
+
- **`approval_step` reads a `(str, Enum)` or `str`-subclass key as its exact `str`** (FAA-196 (30)): such a key waited
|
|
16
|
+
at the start (`outside-mandate: action`) under a mandate that covered the same step's answer.
|
|
17
|
+
- **Node's `JobStore.requestInput` takes plain objects only** (FAA-196 (29)): a request or a requests container that is
|
|
18
|
+
a `Date`, a boxed `String`, a class instance or one whose `method` is inherited is refused with `InteropError`, as
|
|
19
|
+
Python refuses what is no dict; before, it was stored as something other than what was checked.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- `operator_mandate` / `operatorMandate` say that a relayed mandate takes the relay's expiry as `expires_at` /
|
|
24
|
+
`expiresAt` (DEC-0126 OA-3), since a day after a relayed `at` may already have passed (FAA-196 (14)); the default is
|
|
25
|
+
unchanged.
|
|
26
|
+
- `check_dashboard_link.py` says why it keeps its own secret rule rather than importing `fabric_secrets`: it runs alone
|
|
27
|
+
in a dashboard's checkout, and it is broader on purpose (FAA-187 (4)).
|
|
28
|
+
- The answering-agents reference's intro, its Contents list (every section, in order, each anchor its heading's) and
|
|
29
|
+
the Checklist's first line are pinned by `test_answering_agents_prose` (FAA-182 (6)).
|
|
30
|
+
- `docs/evidence/measurements/2026-11-13-faa-256-owner-check-windows.md` records the Node owner check on Windows: a
|
|
31
|
+
median of about 0.31 s per new loopback connection on each side (FAA-256), and that Fabric's hub keeps idle
|
|
32
|
+
connections for Node's default 5 s, above the kit client's 2 s.
|
|
33
|
+
|
|
34
|
+
## 0.84.1 (2026-11-13)
|
|
35
|
+
|
|
36
|
+
0.84.0 was tagged and not published: its release run failed one Node 18 test on the hosted floor runner.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- **The board mandate's linear-time test reads bodies large enough to time** (FAA-135): at 64 KiB a read lasted under a
|
|
41
|
+
millisecond of CPU time, and one garbage collection made the 4x ratio read as 10x on Node 18; it now compares 256 KiB
|
|
42
|
+
with 1 MiB, where linear is still about 4 and quadratic about 16, and repeats each read until 50 ms of CPU time
|
|
43
|
+
(Windows counts it in 15.6 ms ticks, and one short read measured 0), in both twins' tests. No shipped code changes.
|
|
44
|
+
|
|
45
|
+
## 0.84.0 (2026-11-13)
|
|
46
|
+
|
|
47
|
+
Wave 6 of the backlog sweep of 2026-11-12. The contract pin stays at `93e7db16` (`v0.1.0+2026-11-08.1`).
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **Every service kit module carries the package's licence as an SPDX line** (FAA-192 item 15, the operator's decision
|
|
52
|
+
of 2026-11-13): `AGPL-3.0-only OR LicenseRef-PassionCode-Commercial`, right after a shebang or as the first line, so
|
|
53
|
+
every copy `fabric_kit.py install` makes keeps it, an agent whose own files are all rights reserved included; the
|
|
54
|
+
kit's JSON schemas cannot carry a comment. `kit.json`'s digests change for every module. The dashboard kit moves to
|
|
55
|
+
1.1.9 for the same line in its three copied files.
|
|
56
|
+
- **creating-fabric-agents names where an agent reads the private cloud Fabric-server template's repository, never the
|
|
57
|
+
repository** (FAA-192 item 1, the operator's decision of 2026-11-13): the instance's settings or the estate's agent
|
|
58
|
+
map.
|
|
59
|
+
- **`board.slot.returned` means one thing** (FAA-325): the reference service's take-back says `board.slot.taken_back`
|
|
60
|
+
(the slot still away), and the kit says `board.slot.returned` once the slot is held again, after a move back and now
|
|
61
|
+
also once an enroll or replace lands after the operator's take-back (once per take-back in the same process, both
|
|
62
|
+
twins); a take-back of a slot still held marks nothing.
|
|
63
|
+
- The supervisors' well-known reader uses the kit's one loopback rule (`fabric_socket_proof.loopback_host` /
|
|
64
|
+
`loopbackHost`): `127.1`, `2130706433`, `0x7f.1` and names under `.localhost` go on the checked connection (FAA-326).
|
|
65
|
+
- `fabric_peer_owner` no longer adds the kit folder to the host's `sys.path` (FAA-327): it asks the `fabric_socket_proof`
|
|
66
|
+
beside it, the host's imported module when that is the same file (one calibration in a process), else that file by
|
|
67
|
+
its path; a copy vendored alone keeps the table's answer, and every kit install that brings `fabric_peer_owner` still
|
|
68
|
+
brings `fabric_socket_proof`. `PEER_OWNER_VERSION` is `1.3.1+kit.8`.
|
|
69
|
+
- The supervisors' well-known reader refuses unread a loopback address the kit's rule does not take, with a zone
|
|
70
|
+
(`[::1%lo0]`) or IPv4-mapped (`[::ffff:127.0.0.1]`), where `urlopen` or `fetch` would reach the listener without the
|
|
71
|
+
owner check (0.84.0 seam reading).
|
|
72
|
+
- `test/validate.py` reads the private-terms list with the functions `admit.py` ships (`terms_file`, `terms_pattern`,
|
|
73
|
+
`term_lines`, `listed_files`), pinned to one case table; `admit.py`'s file listing no longer fails when `git` cannot
|
|
74
|
+
run (FAA-328).
|
|
75
|
+
|
|
76
|
+
### Upgrading
|
|
77
|
+
|
|
78
|
+
- A dashboard or feed that reads `board.slot.returned` as the operator's take-back request reads
|
|
79
|
+
`board.slot.taken_back` now (FAA-325).
|
|
80
|
+
|
|
3
81
|
## 0.83.1 (2026-11-13)
|
|
4
82
|
|
|
5
83
|
0.83.0 was tagged and not published: its release run failed one Windows test of the tailnet identity module.
|
package/README.md
CHANGED
|
@@ -263,7 +263,8 @@ claude plugin validate . --strict
|
|
|
263
263
|
unquoted value holding `: ` fails it. `python3 test/validate.py --frontmatter <SKILL.md ...>`
|
|
264
264
|
checks copies installed elsewhere, such as `~/.agents/skills/*/SKILL.md`. Before a push or a release,
|
|
265
265
|
`python3 test/validate.py --private-terms` checks the tracked files against the operator's private-terms list
|
|
266
|
-
(path and line only; exit 2 when the list is absent, which is not a pass; CONTRIBUTING.md step 6)
|
|
266
|
+
(path and line only; exit 2 when the list is absent, which is not a pass; CONTRIBUTING.md step 6), read with the same
|
|
267
|
+
functions as `creating-fabric-agents/scripts/admit.py`'s `private-terms` step (FAA-328). Start in
|
|
267
268
|
[AGENTS.md](AGENTS.md); contributions follow [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
268
269
|
|
|
269
270
|
## Use
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.0",
|
|
4
4
|
"description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "fabric-agent-adapter",
|
|
4
4
|
"displayName": "Fabric Agent Adapter",
|
|
5
5
|
"description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks; and put an agent on a standing watch over a product (observer mode).",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.85.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -9,7 +9,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
9
9
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode.
|
|
10
10
|
metadata:
|
|
11
11
|
author: PassionCode.ai
|
|
12
|
-
version: "0.
|
|
12
|
+
version: "0.85.0"
|
|
13
13
|
contract-version: "0.1.0"
|
|
14
14
|
contract-commit: "93e7db164c7829e2783b4b7705c4113bb5201131"
|
|
15
15
|
---
|
|
@@ -46,6 +46,9 @@ def has_jwt(text):
|
|
|
46
46
|
return False
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
# Kept here, not imported: this gate runs alone in a dashboard's own checkout with no kit beside it, and its three copies
|
|
50
|
+
# stay byte-identical (test_dashboard_links.py). It is broader than `fabric_secrets` on purpose (FAA-136, FAA-187 (4)): a
|
|
51
|
+
# page link that only looks like a secret is refused, since a link is never a place for one.
|
|
49
52
|
# The contract's SECRET_VALUE at the pin (DEC-0151): `Bearer ` at a value's start in any case, or a provider key with its
|
|
50
53
|
# prefix in its canonical case after a boundary (the start, a character that is no ASCII letter or digit, or an escape);
|
|
51
54
|
# an `sk-` key holds a digit and an upper-case letter with 16 or more characters, or a digit with 32 or more.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
"""Identifier equality (contract DEC-0076): two identifiers are the same when their normal forms are equal.
|
|
2
3
|
|
|
3
4
|
A port of the contract's `src/identifiers.ts`, held to its `fixtures/vectors/identifiers.json`. The normal form of a URI
|
package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_secrets.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
2
3
|
"""The contract's one credential detector (Fabric Agent Contract DEC-0044, `src/secret-shape.ts` at the pin): a name
|
|
3
4
|
that can only carry a credential, a value shaped like one, a launch argument that carries one, and a URL that does
|
|
4
5
|
(LC-21). A port held to the contract's own answers by test/fixtures/contract/profile-vectors.json. Standard library
|
|
@@ -9,7 +9,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
9
9
|
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. On macOS 27.2 run kit services and the probe on Apple's /usr/bin/python3.
|
|
10
10
|
metadata:
|
|
11
11
|
author: PassionCode.ai
|
|
12
|
-
version: "0.
|
|
12
|
+
version: "0.85.0"
|
|
13
13
|
contract-version: "0.1.0"
|
|
14
14
|
extension: "fabric-service/0.1"
|
|
15
15
|
extension-commit: "93e7db164c7829e2783b4b7705c4113bb5201131"
|
|
@@ -361,7 +361,7 @@ Whoever owns the repository, an agent with a page gets the dashboard rule block
|
|
|
361
361
|
(below). org-index `scripts/check_format.py` reports 0 findings for it before it is called done. **An agent
|
|
362
362
|
someone builds for themselves is not a PassionCode.ai repository:** its licence is its owner's choice, the organization
|
|
363
363
|
publishes and lists nothing about it, of these files one built new needs only a `LICENSE` naming its copyright holder (copied kit files keep
|
|
364
|
-
theirs), and the verified MCP quick start teaches anyone to drive it. The kit's files stay AGPL-3.0-only or the
|
|
364
|
+
theirs, each service kit module in its own SPDX line), and the verified MCP quick start teaches anyone to drive it. The kit's files stay AGPL-3.0-only or the
|
|
365
365
|
PassionCode commercial licence there, in an agent built for a client too.
|
|
366
366
|
|
|
367
367
|
## Online services: the remote placement
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.9 · Fabric's button (Fabric Agent Contract DEC-0040, FB-1…FB-8, FL-1…FL-6)
|
|
2
|
+
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
2
3
|
Load it same-origin, after fabric-dashboard.css, with the service it opens Fabric on:
|
|
3
4
|
<script src="fabric-button.js" defer data-service="example-agent.default" data-service-name="Example Agent"
|
|
4
5
|
data-project="project-a" data-project-name="Project A"></script>
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
(function (root) {
|
|
12
13
|
'use strict';
|
|
13
14
|
|
|
14
|
-
var VERSION = '1.1.
|
|
15
|
+
var VERSION = '1.1.9';
|
|
15
16
|
var COOKIE = 'fabric_button';
|
|
16
17
|
var GET_FABRIC = 'https://passioncode.ai/fabric';
|
|
17
18
|
var ABSENT_AFTER_MS = 1500;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.9 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
|
|
2
|
+
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
2
3
|
A Fabric service dashboard shown inside a host pane: usable from 360 CSS px up, navigation always
|
|
3
4
|
reachable, wide content in its own scroll box, one vertical scroller, appearance from the host.
|
|
4
5
|
Copy this file next to fabric-dashboard.js; do not edit it in place. Put the page's own rules in
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/* fabric-dashboard-kit@1.1.
|
|
1
|
+
/* fabric-dashboard-kit@1.1.9 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
|
|
2
|
+
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
2
3
|
Load it same-origin with <script src="fabric-dashboard.js" defer></script>: no inline script, no
|
|
3
4
|
eval, nothing from a CDN. It applies the host's appearance (ED-6, ED-8), folds navigation that
|
|
4
5
|
does not fit into a More menu (ED-3), makes wide boxes keyboard-reachable (ED-4) and keeps
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
'use strict';
|
|
9
10
|
|
|
10
11
|
var KIT = 'fabric-dashboard-kit';
|
|
11
|
-
var VERSION = '1.1.
|
|
12
|
+
var VERSION = '1.1.9';
|
|
12
13
|
/* fabric-dashboard-kit:theme-ids:begin */
|
|
13
14
|
var THEMES = ['graphite', 'fabric', 'paper', 'forest', 'ocean', 'ember', 'contrast'];
|
|
14
15
|
/* 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.9",
|
|
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": "99ccf34065a2cfdfafb7af17b9b6c178bf6c871b6fa8e771d997f820726037ae",
|
|
19
|
+
"fabric-dashboard.js": "cc2a02e27118df56db8d504c1894ea3ddc5fe71a0029c9ce4fb97aea44b54a76",
|
|
20
|
+
"fabric-button.js": "1e70716768202edb5323b7ee081a074fa447f0f51b1aececa0ec659e8a320e20",
|
|
21
21
|
"themes.json": "511839f1a1a83eb37fadfd132791474497d5c28c5091700b9aa31ad076e359b5"
|
|
22
22
|
},
|
|
23
23
|
"history": {
|
|
@@ -69,6 +69,11 @@
|
|
|
69
69
|
"fabric-dashboard.css": "0c58c2758e780f4f520d3ea45d69a7d4221ad97cdc7e6999da7c7511e6beb96c",
|
|
70
70
|
"fabric-dashboard.js": "dfaef6b91102817061f612aea1f4b5a85699a890d7f4fbda2780dc153f2e5da1",
|
|
71
71
|
"fabric-button.js": "11ebad0cc598b09f034666be377caf0edc0042e9e86d7d8e8292dda57789be7f"
|
|
72
|
+
},
|
|
73
|
+
"1.1.9": {
|
|
74
|
+
"fabric-dashboard.css": "99ccf34065a2cfdfafb7af17b9b6c178bf6c871b6fa8e771d997f820726037ae",
|
|
75
|
+
"fabric-dashboard.js": "cc2a02e27118df56db8d504c1894ea3ddc5fe71a0029c9ce4fb97aea44b54a76",
|
|
76
|
+
"fabric-button.js": "1e70716768202edb5323b7ee081a074fa447f0f51b1aececa0ec659e8a320e20"
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
}
|
|
@@ -341,7 +341,9 @@ held and not transferred). The responder keeps that move instead of undoing it:
|
|
|
341
341
|
- Otherwise only the operator brings the slot back: `take_back(capability)` (`takeBack`) forgets the record, and wins over a move
|
|
342
342
|
being read at the same time: the move is written under the responder's lock (Node: on the fence queue, after any fenced
|
|
343
343
|
call in flight) and only while the record is unchanged (FAA-158). Never edit the
|
|
344
|
-
checkpoint's `slots` record by hand to undo a move.
|
|
344
|
+
checkpoint's `slots` record by hand to undo a move. Once the slot is held again after a take-back (an enroll or a
|
|
345
|
+
replace lands, in the same process), the kit says `board.slot.returned` (info, once per take-back; FAA-325), as it
|
|
346
|
+
does for a move back. In the same board
|
|
345
347
|
session the next tick enrolls once the other session lets the slot go (a live holder is waited for) and takes the work
|
|
346
348
|
left `lapsed` back with a transfer. A restart or reconnect before that, with accepted work waiting for the slot, takes it
|
|
347
349
|
back at once by `com.responder_replace`, as a restart did before 0.53.0: the operator asked for the slot back, so the
|
|
@@ -354,7 +356,8 @@ held and not transferred). The responder keeps that move instead of undoing it:
|
|
|
354
356
|
(`interop.well-known-capabilities`): an agent whose MCP client sets `_meta` calls it over `/mcp` with the operator's
|
|
355
357
|
decision in `_meta.decision` (a call without one is `operator-decision-required`); Claude Code and Codex send
|
|
356
358
|
arguments only, so until CT-125 they hand the operator the page as Fabric Dashboards' `open_link`. Either door records
|
|
357
|
-
the take-back as a `board.slot.
|
|
359
|
+
the take-back as a `board.slot.taken_back` event (info, the capability as its subject; the slot is still away, so never
|
|
360
|
+
`board.slot.returned`, which is the kit's and means held again, FAA-325) whose sentence says the route in
|
|
358
361
|
words and whose `data` holds `by`, `via` and the `caller` (none when the feed refuses the caller), never the decision's words; a repeat after a lost answer is answered `{capability, moved: false}`. A service built on the kit declares it as an operator action, a button with its tool ([Every button has a
|
|
359
362
|
tool](../SKILL.md), `fabric-actions/0.1`) with gate `relayed` (the operator's decision), never `none`, so a call
|
|
360
363
|
without the operator's relayed decision is refused; on a server that reads mandates (`agent_id`) it also names its effect class, for example
|
|
@@ -394,7 +397,9 @@ checked by FAC-SEM-101 (no credential in data): `board.request.completed`, `boar
|
|
|
394
397
|
`board.reconcile.needed`, `board.slot.contested`, `board.slot.moved`, `board.slot.refused`, `board.access.needed`, `board.blocked`,
|
|
395
398
|
`board.down`, each notifying episode said once, and `board.outcome.invalid` (warning) when a handler's outcome fails
|
|
396
399
|
its checks and is not sent, and `board.request.mandate_unread` (warning) when a request's mandate is not read (above). The operator's hold (below) adds `board.held`, `board.slot.held`,
|
|
397
|
-
`board.slot.released` and `board.request.waiting`.
|
|
400
|
+
`board.slot.released` and `board.request.waiting`. A slot held again after a move back or a take-back is
|
|
401
|
+
`board.slot.returned` (info). The reference service adds `board.slot.taken_back` at a take-back, when the operator asks
|
|
402
|
+
for the slot (FAA-325).
|
|
398
403
|
|
|
399
404
|
`check_service.py <id> [--board-kit <the service's fabric_board.py or fabric-board.mjs>]` rule **board.responder**:
|
|
400
405
|
`NOT_RUN` when the well-known `protocols` names no `fabric-project-comms` revision; `FAIL` for a revision this kit does
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md
CHANGED
|
@@ -39,7 +39,7 @@ python3 <skill-dir>/scripts/dashboard_kit.py install <the directory your page's
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
It copies `fabric-dashboard.css` and `fabric-dashboard.js` (each starts with
|
|
42
|
-
`fabric-dashboard-kit@<version
|
|
42
|
+
`fabric-dashboard-kit@<version>`, then, since 1.1.9, the package's SPDX licence line, which a copy keeps: FAA-192). Serve both same-origin and link them; nothing is inline:
|
|
43
43
|
|
|
44
44
|
```html
|
|
45
45
|
<html lang="en" data-fd-appearance="scheme theme">
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md
CHANGED
|
@@ -11,6 +11,14 @@ A module's comments write an example URL with credentials with its scheme in ang
|
|
|
11
11
|
can copy modules unchanged; the package's CHANGELOG, a record of released notes and no module, keeps its old
|
|
12
12
|
examples as written.
|
|
13
13
|
|
|
14
|
+
Every module carries the package's licence as its own SPDX line, `SPDX-License-Identifier: AGPL-3.0-only OR
|
|
15
|
+
LicenseRef-PassionCode-Commercial`, right after the shebang or as its first line (since 0.84.0, FAA-192), so every
|
|
16
|
+
copy `install` makes keeps it, in an agent whose own files are all rights reserved too: that agent's `LICENSE` covers
|
|
17
|
+
its holder's files, the line covers the kit's. The line is part of the module's bytes and of its digest in
|
|
18
|
+
`kit.json`, so a copy `status` calls `current` carries it. The schemas the kit ships beside a module (`*.schema.json`)
|
|
19
|
+
are JSON data and cannot carry a comment; they come under the same licence with the module that reads them. Tests:
|
|
20
|
+
`test_every_kit_module_carries_its_spdx_line`, `test_an_installed_copy_keeps_its_spdx_line`.
|
|
21
|
+
|
|
14
22
|
## Contents
|
|
15
23
|
|
|
16
24
|
- [Install, status, build](#install-status-build)
|
|
@@ -60,7 +68,7 @@ A module imports only modules listed before it in `kit.json`, so the kit has no
|
|
|
60
68
|
| L0 | `fabric_identifiers` | identifier equality by normal form (DEC-0076) |
|
|
61
69
|
| L0 | `fabric_secrets` | the contract's one credential detector (DEC-0044) |
|
|
62
70
|
| L0 | `fabric_socket_proof` | this OS account's own TCP sockets, read from its own processes, and the two proofs they give on a restricted macOS table (DEC-0155 RT-2, FAA-292; FAA-272): `accepted` (the server end of a connection held by one of this account's processes) and `own_listener` (its listener on exactly 127.0.0.1); Python reads them through libproc (Project Observatory's `peer_owner` 1.3.1 reader, calibrated on a pair of its own) and lsof when libproc is unavailable, the Node twin through `lsof -nP -a -u <uid> -iTCP:<port> -sTCP:<state> -F pun`; `fabric_peer_owner` asks it when it sits beside it |
|
|
63
|
-
| L0 | `fabric_peer_owner` | which OS account owns each end of a loopback connection, from the computer's socket table (DEC-0154 HA-2, FAA-226): `listener`, `server_end`, `peer`, `CheckedHTTPConnection`; the Python file is Project Observatory's `peer_owner.py`, vendored from commit `f86f0622` (1.1.0) and read against `2180235c` (1.2.0, whose Linux rule it carries) and `a69c6fee` (1.3.1), with the readings its header names (`1.3.1+kit.
|
|
71
|
+
| L0 | `fabric_peer_owner` | which OS account owns each end of a loopback connection, from the computer's socket table (DEC-0154 HA-2, FAA-226): `listener`, `server_end`, `peer`, `CheckedHTTPConnection`; the Python file is Project Observatory's `peer_owner.py`, vendored from commit `f86f0622` (1.1.0) and read against `2180235c` (1.2.0, whose Linux rule it carries) and `a69c6fee` (1.3.1), with the readings its header names (`1.3.1+kit.8`), the Node twin reads netstat, `/proc` and the owner SID where Python reads `sysctl`, `/proc` and `GetExtendedTcpTable`; on a restricted macOS table (FAA-267) `fabric_socket_proof`, when beside it (the host's imported copy if it is that file, else that file by its path; never through `sys.path`, and every kit install copies it, FAA-327), proves a server end or listener this account's processes hold (RT-2), and after it a caller may vouch with a pid it started, proved by `lsof -p` (RT-3) |
|
|
64
72
|
| L0 | `fabric_tailnet` | who calls an agent behind `tailscale serve` and what that person may open (FAA-297): `Tailscale-User-Login` only on the agent's own serve listener from a loopback peer, groups from a generated `tailnet-perimeter/1` file, a personal SHA-256-stored key for MCP no wider than the groups; `authorize`, `load_perimeter`, `load_keys`, `hash_key`, refusals 401/403 with a code ([surfaces-and-auth.md](surfaces-and-auth.md#behind-tailscale-serve)) |
|
|
65
73
|
| L0 | `fabric_tailnet_identity` | a person's identity at every door (dashboard, MCP, the service's own) of a service published through `tailscale serve` (FAA-324): `Tailscale-User-Login` believed only when the service listens on a loopback address and the peer is loopback, groups and per-door rules from the organization's `tailnet-groups/1` file (schema `tailnet-groups.schema.json`, shipped beside it as data), read again on change and closing every door while unreadable or invalid; `TailnetIdentity`, `decide`, `load_groups`, `send_refusal`, every refusal 403 with a code and a sentence ([surfaces-and-auth.md](surfaces-and-auth.md#a-groups-file-at-every-door)) |
|
|
66
74
|
| L1 | `fabric_crypto` | Ed25519 signing (a Montgomery ladder that does not branch on the key) and verification, P-256 verification, base64url, sha256 |
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md
CHANGED
|
@@ -55,8 +55,9 @@ on a listener of this OS account (DEC-0154 HA-2: another account's listener is `
|
|
|
55
55
|
LaunchDaemon's root installer reads it as *The system domain* says). `well_known_of(origin)` / `wellKnownOf(origin)` read
|
|
56
56
|
it so a status tells HA-2's order apart: None / null when nothing answers (`down`), a `ForeignUserAnswer` whose
|
|
57
57
|
`reason` starts `foreign-user` or `table-restricted`, else the document; `fetch_well_known` keeps answering None for
|
|
58
|
-
both (FAA-259). Every loopback spelling of an origin (`127.0.0.1`, another `127/8` address
|
|
59
|
-
|
|
58
|
+
both (FAA-259). Every loopback spelling of an origin (`127.0.0.1`, another `127/8` address in any form a URL parser
|
|
59
|
+
reads, such as `127.1` or `2130706433`, `localhost` or a name under `.localhost`, `[::1]`) is read on a checked connection
|
|
60
|
+
(FAA-257; the kit's one rule, `fabric_socket_proof.loopback_host` / `loopbackHost`, since FAA-326). `launchd_install` takes an injected reader, `fetch_well_known=` and
|
|
60
61
|
`fetch_job_well_known=`, as the Node `launchdInstall` takes `fetchWellKnown` and `fetchJobWellKnown`.
|
|
61
62
|
`status` is `starting`, `ready`, `degraded` or `stopping`; `degraded` is always present, and an empty list asserts
|
|
62
63
|
full health. A process that cannot serve does not answer, and a host derives `down`. An install or upgrade polls
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_link.py
CHANGED
|
@@ -46,6 +46,9 @@ def has_jwt(text):
|
|
|
46
46
|
return False
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
# Kept here, not imported: this gate runs alone in a dashboard's own checkout with no kit beside it, and its three copies
|
|
50
|
+
# stay byte-identical (test_dashboard_links.py). It is broader than `fabric_secrets` on purpose (FAA-136, FAA-187 (4)): a
|
|
51
|
+
# page link that only looks like a secret is refused, since a link is never a place for one.
|
|
49
52
|
# The contract's SECRET_VALUE at the pin (DEC-0151): `Bearer ` at a value's start in any case, or a provider key with its
|
|
50
53
|
# prefix in its canonical case after a boundary (the start, a character that is no ASCII letter or digit, or an escape);
|
|
51
54
|
# an `sk-` key holds a digit and an upper-case letter with 16 or more characters, or a digit with 32 or more.
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a-server.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The serving side and a bounded client of A2A 1.0 (FAA-10, DEC-0122): an Agent Card built from the service's
|
|
2
3
|
// capabilities (agentCard, checked by agentCardFindings before it is served), the JSON-RPC binding (A2ABinding:
|
|
3
4
|
// SendMessage, SendStreamingMessage, GetTask, CancelTask) mapped onto the interop job store (a task is a job, a choice
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The reading side of an A2A Agent Card (DEC-0122): the well-known document's surfaces.a2a member, read as the contract's
|
|
2
3
|
// schema reads it (a2aSurfaceFindings, a2aView; a2aSurface builds one), and what a public card must not carry
|
|
3
4
|
// (agentCardFindings): no member about the running process, no secret, no securitySchemes entry naming the descriptor's
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-actions.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Every action a person has, its agent tool and who decides it: fabric-actions/0.1, the extension keyed
|
|
2
3
|
// extensions/actions/0.1 (DEC-0121, FAC-SEM-142). Part of the Node service kit (layer L3); the twin of fabric_actions.py.
|
|
3
4
|
//
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-auth.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Who may call a service: the descriptor token, the network guard, the operator's one-time login and session, remote placement (DEC-0019), the feed client's token header.
|
|
2
3
|
// Part of the Node service kit (FAA-65, layer L3); the twin of fabric_auth.py. Node 20+, no dependency.
|
|
3
4
|
import crypto from 'node:crypto';
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Settings backups (DEC-0025, FAC-SEM-035): canonical form, digest, write, list, check, restore.
|
|
2
3
|
// Part of the Node service kit (FAA-65, layer L3); the twin of fabric_backups.py. Node 20+, no dependency.
|
|
3
4
|
import crypto from 'node:crypto';
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// What every module of the Node service kit shares: the protocol name, ServiceError, ids, nowIso and expand.
|
|
2
3
|
// Part of the Node service kit (FAA-65, layer L1); the twin of fabric_base.py. Node 20+, no dependency.
|
|
3
4
|
import os from 'node:os';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// A fixture conversation for the probe (check_service.py, rule board.responder): a scripted board a responder can run against without Fabric.
|
|
2
3
|
// Part of the Node board connector (FAA-65, layer L4); the twin of fabric_board_fixture.py. Node 20+, no dependency.
|
|
3
4
|
import fs from 'node:fs';
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-link.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The board link (DEC-0078, FAA-12b): the board session over the hub, the fsynced checkpoint and a claimed request as data.
|
|
2
3
|
// Part of the Node board connector (FAA-65, layer L4), below the responder in fabric-board-session.mjs, which re-exports
|
|
3
4
|
// these names; the twin of fabric_board_link.py. Node 18+, no dependency.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The board responder (DEC-0078, FAA-12b): the work context a handler sees and the responder loop. The session, the
|
|
2
3
|
// checkpoint and the request live in fabric-board-link.mjs and are re-exported here.
|
|
3
4
|
// Part of the Node board connector (FAA-65, layer L4); the twin of fabric_board_session.py. Node 20+, no dependency.
|
|
@@ -124,6 +125,7 @@ export class Responder extends SlotKeeper {
|
|
|
124
125
|
/** The first pause under an operator's hold (DEC-0079); it doubles to HOLD_RETRY_MAX_SECONDS. */
|
|
125
126
|
this.holdDelay = POLL_SECONDS;
|
|
126
127
|
this.onHold = new Set();
|
|
128
|
+
this.takenBack = new Set(); // capabilities the operator took back, not yet held again (FAA-325)
|
|
127
129
|
/** One fenced call at a time, and the entry edits beside them (FAA-77, finding 36). */
|
|
128
130
|
this.fenceQueue = Promise.resolve();
|
|
129
131
|
this.toResume = []; // transferred requests waiting until nothing runs (finding 39)
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-shapes.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The project board's wire (fabric-project-comms/0.1, DEC-0022, DEC-0073, DEC-0077): constants, refusal codes, the request digest, the closed shapes the kit reads back, evidence.
|
|
2
3
|
// Part of the Node board connector (FAA-65, layer L4); the twin of fabric_board_shapes.py. Node 20+, no dependency.
|
|
3
4
|
import crypto from 'node:crypto';
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-slots.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The board responder's slot records (FAA-155, FAA-163): the generation it holds each slot at, a move to another
|
|
2
3
|
// session and its take-back, and a capability whose enroll was refused, retried on its own. Part of the board
|
|
3
4
|
// connector (FAA-65, layer L4); Responder (fabric-board-session.mjs) extends SlotKeeper.
|
|
@@ -27,6 +28,9 @@ export class SlotKeeper {
|
|
|
27
28
|
this.confirmed[capability] = generation;
|
|
28
29
|
delete this.said[`board.slot.refused:${capability}`]; // held again: a later refusal is said again
|
|
29
30
|
delete this.said[`board.slot.contested:${capability}`]; // and a later contest, by enroll or replace
|
|
31
|
+
if (this.takenBack.delete(capability)) { // FAA-325: held again after the operator's take-back, said once
|
|
32
|
+
this.emit('board.slot.returned', 'info', `The ${capability} slot on this Project is this service's again: the operator took it back, and it answers it from now on.`, { capability, generation });
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
/** The slot record, best effort: one that cannot be written now is written at the next receipt. */
|
|
@@ -212,6 +216,7 @@ export class SlotKeeper {
|
|
|
212
216
|
const back = await this.locked(() => {
|
|
213
217
|
if (!sameRecord(this.checkpoint.slots[capability], held)) return false; // a takeBack forgot it; its own next tick enrolls
|
|
214
218
|
this.slots[capability] = { state: 'held', generation, renewedAt: -Infinity }; // no lease yet
|
|
219
|
+
this.takenBack.delete(capability); // said below as a move back, once
|
|
215
220
|
this.heldAt(capability, generation);
|
|
216
221
|
delete this.said['board.slot.moved']; // a later move is said again
|
|
217
222
|
return true;
|
|
@@ -230,8 +235,11 @@ export class SlotKeeper {
|
|
|
230
235
|
this.checkpoint.slot(capability, null);
|
|
231
236
|
delete this.claimKeys[capability]; // a receipt from before the take-back may be dead
|
|
232
237
|
this.probing.delete(capability);
|
|
233
|
-
|
|
238
|
+
const state = this.slots[capability]?.state;
|
|
239
|
+
if (state === 'moved') this.slots[capability] = { state: 'contested', renewedAt: 0 };
|
|
234
240
|
delete this.said['board.slot.moved'];
|
|
241
|
+
// board.slot.returned is said once the slot is held again (FAA-325); a slot still held has nothing to say
|
|
242
|
+
if (state !== 'held') this.takenBack.add(capability);
|
|
235
243
|
}
|
|
236
244
|
|
|
237
245
|
// -- one capability's refusal (FAA-163) --
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The project board connector, Node: the facade (fabric-project-comms/0.1; the twin of fabric_board.py).
|
|
2
3
|
// Since 0.40.0 (FAA-65) it is layered modules: fabric-board-shapes, fabric-board-link (since 0.41.0), fabric-board-session and
|
|
3
4
|
// fabric-board-fixture. This file re-exports everything it exported at 0.39.1. Node 20+, no dependency.
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ceremonies.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The estate ceremonies' headless join (contract DEC-0084), the Node kit; the twin of fabric_ceremonies.py, answer for
|
|
2
3
|
// answer (test/fixtures/contract/ceremony-vectors.json). Node built-ins only.
|
|
3
4
|
// verifyEnrollToken (the hub's and the node's verifier of an enroll-token/1), enrollJoinInput (what the joining machine
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-connections.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// What an agent uses: fabric-connections/0.1, the extension keyed extensions/connections/0.1 (DEC-0096, FAC-SEM-127).
|
|
2
3
|
// connectionsView reads a well-known document as the contract's connectionsView does (it never throws);
|
|
3
4
|
// connectionsExtension builds the `extensions` entry a service declares, `state` from its own checks and its degraded[].
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-context.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// One instance per context (FAA-125, organization row N-11; contract DEC-0082, "One instance per context on a machine"):
|
|
2
3
|
// from a context, `personal` or `org:<orgId>`, the service instance, its folders, descriptor and instance lock.
|
|
3
4
|
// Part of the Node service kit (layer L3, after fabric-descriptor); the twin of fabric_context.py, answer for answer
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-crypto.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The Node kit's cryptography helpers, once (FAA-65, layer L1); the twin of fabric_crypto.py. Signature verification
|
|
2
3
|
// itself is Node's (`crypto.verify`); what lives here is what the runtime does not refuse on its own: keys of small
|
|
3
4
|
// order (DEC-0045) and P-256 points off the curve, plus sha256. Node 20+, no dependency.
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The callee's side of fabric-delegation/0.1 (Fabric Agent Contract DEC-0039, Fabric ADR-0144): check a
|
|
2
3
|
// delegation token or an approval offline against the estate's published keys, and answer `ok` or one refusal
|
|
3
4
|
// code. A port of the contract's `src/delegation.ts` at the pinned revision; the shared vectors in
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// How a service is found (fabric-service/0.1): its descriptor, peers and app descriptors (DEC-0061, DEC-0069), build identity and the well-known document.
|
|
2
3
|
// Part of the Node service kit (FAA-65, layer L3); the twin of fabric_descriptor.py. Node 20+, no dependency.
|
|
3
4
|
import { spawnSync } from 'node:child_process';
|
|
@@ -18,7 +19,7 @@ import { ROUTES, isPlainObject } from './fabric-usage.mjs';
|
|
|
18
19
|
// document's `extensions`. The kit is assets/dashboard-kit; its version is the one in kit.json.
|
|
19
20
|
export const DASHBOARD_EXTENSION_KEY = 'https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1';
|
|
20
21
|
|
|
21
|
-
export const DASHBOARD_KIT = 'fabric-dashboard-kit@1.1.
|
|
22
|
+
export const DASHBOARD_KIT = 'fabric-dashboard-kit@1.1.9';
|
|
22
23
|
|
|
23
24
|
export const REFERENCE_THEMES = ['graphite', 'fabric', 'paper', 'forest', 'ocean', 'ember', 'contrast'];
|
|
24
25
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate-rules.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// `estate-record/1` (Fabric Agent Contract DEC-0055): the record's own rules, without a verifier; the twin of
|
|
2
3
|
// fabric_estate_rules.py. The contract's src/estate-record-rules.ts at the pin, held to the contract's own vectors
|
|
3
4
|
// (test/fixtures/contract/estate-vectors.json). Split from fabric-estate.mjs (0.52.0, decision D8) so each module stays
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// `estate-record/1` (Fabric Agent Contract DEC-0055): verify an estate revision and check its rules, the twin of
|
|
2
3
|
// fabric_estate.py. The contract's src/estate-record-rules.ts, src/webauthn.ts and src/p256.ts at the pin, held to the
|
|
3
4
|
// contract's own vectors (test/fixtures/contract/estate-vectors.json):
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-events.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// A service's events (DEC-0029): making them, paging them and the JSONL event log.
|
|
2
3
|
// Part of the Node service kit (FAA-65, layer L3); the twin of fabric_events.py. Node 20+, no dependency.
|
|
3
4
|
import { ServiceError } from './fabric-base.mjs';
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-holds.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Work a service holds by its own limits, said to its caller and its operator (FAA-298): a held job's statusMessage in
|
|
2
3
|
// the contract's pause grammar (`quota-exhausted[ until <until>]: waiting <reason> since <since>[: <message>]`; the
|
|
3
4
|
// pinned interop-job schema is closed, so `waiting {reason, since, until, message}` rides statusMessage, never a field
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// An outbound HTTP client for a service: one deadline across every attempt, bounded retries with jittered backoff,
|
|
2
3
|
// `Retry-After` honoured up to a cap, a response size cap, and no secret in an error. The twin of fabric_http.py:
|
|
3
4
|
// the same rules, the same cases (test/fixtures/kit-http-cases.json).
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// The Fabric hub's door, as a service agent reaches it (fabric-hub/0.1; Fabric ADR-0115 §1, ADR-0149 §4; FAA-12b).
|
|
2
3
|
// The twin of fabric_hub.py, same rules and the same answers; Node built-ins only.
|
|
3
4
|
//
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-identifiers.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Identifier equality (contract DEC-0076): two identifiers are the same when their normal forms are equal. A port of the
|
|
2
3
|
// contract's src/identifiers.ts (types removed), held to its fixtures/vectors/identifiers.json; the twin of
|
|
3
4
|
// fabric_identifiers.py. Nothing here throws.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// fabric-interop/0.1, the rule layer: the extension's names and limits, its errors, the trace context (C3.4), a usage
|
|
2
3
|
// object's reading (C3.2) and the job limits and uncertain effects (DEC-0087). Every function answers by a rule and
|
|
3
4
|
// touches no file; fabric-interop.mjs builds the tools, the envelope and the job store on it and re-exports every public
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// Reference kit for the fabric-interop/0.1 extension — Node.js 20+, no dependencies.
|
|
2
3
|
// The Node twin of fabric_interop.py: the same rules and the same job file format, so a
|
|
3
4
|
// job written by one kit is read by the other. The minimal MCP dispatcher is Python-only;
|
|
@@ -271,8 +272,11 @@ export class JobStore {
|
|
|
271
272
|
// job's private part (the format fabric_interop.py writes) so a service reads an answer's _meta.mandate for that step.
|
|
272
273
|
// A step is kept as the gate reads it (keptStep), so a job's start and its answer agree.
|
|
273
274
|
requestInput(jobId, inputRequests, statusMessage, { steps } = {}) {
|
|
275
|
+
// a plain object (its prototype Object's or none), as Python's dict: a Date, a boxed String or a class instance is
|
|
276
|
+
// not stored as what was checked (FAA-196 (29))
|
|
277
|
+
const plainObject = (value) => value !== null && typeof value === 'object' && [Object.prototype, null].includes(Object.getPrototypeOf(value));
|
|
274
278
|
const entries = Object.entries(inputRequests ?? {});
|
|
275
|
-
if (!entries.length ||
|
|
279
|
+
if (!entries.length || !plainObject(inputRequests)) throw new InteropError('input_required needs a JSON object of at least one input request.'); // a JSON object of requests, first (unit 38, 40)
|
|
276
280
|
if (steps !== null && steps !== undefined && (typeof steps !== 'object' || Array.isArray(steps))) { // FAA-196 (26)
|
|
277
281
|
throw new InteropError('steps maps an input request\'s key to its approval step: a JSON object, or none.');
|
|
278
282
|
}
|
|
@@ -281,7 +285,7 @@ export class JobStore {
|
|
|
281
285
|
kept[key] = Object.hasOwn(inputRequests, key) && step !== null && step !== undefined ? keptStep(step) : {};
|
|
282
286
|
if (!EFFECT_CLASSES.includes(kept[key].effect)) throw new InteropError(`Step ${key}: an input request's key with its effect class (DEC-0125).`);
|
|
283
287
|
}
|
|
284
|
-
for (const [key, request] of entries) if (!KEY.test(key) || request
|
|
288
|
+
for (const [key, request] of entries) if (!KEY.test(key) || !plainObject(request) || !Object.hasOwn(request, 'method') || request.method !== 'elicitation/create') throw new InteropError(`Input request ${key} must be a keyed elicitation/create request.`);
|
|
285
289
|
const [finding] = inputRequestLinkFindings({ inputRequests }); // FAC-SEM-143 (D12)
|
|
286
290
|
if (finding) throw new InteropError(`${finding.instancePath}: ${finding.message}`);
|
|
287
291
|
return this.transition(jobId, 'input_required', { inputRequests, statusMessage }, { steps: kept });
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-jsvalue.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
1
2
|
// JavaScript's view of JSON values, once for the whole Node kit (FAA-65, layer L0); the twin of fabric_jsvalue.py.
|
|
2
3
|
// The contract's answers are computed by TypeScript; every reader in the kit takes these helpers from here:
|
|
3
4
|
// isObject, isString, objects (an array's object items), indexed (with their index as written), show (the
|