@passioncode-ai/fabric-agent-adapter 0.83.1 → 0.84.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +2 -1
  3. package/package.json +1 -1
  4. package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
  5. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +1 -1
  6. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_identifiers.py +1 -0
  7. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_secrets.py +1 -0
  8. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +2 -2
  9. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-button.js +3 -2
  10. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +2 -1
  11. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +3 -2
  12. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json +9 -4
  13. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +8 -3
  14. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +1 -1
  15. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +9 -1
  16. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +3 -2
  17. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a-server.mjs +1 -0
  18. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-a2a.mjs +1 -0
  19. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-actions.mjs +1 -0
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-auth.mjs +1 -0
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +1 -0
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-base.mjs +1 -0
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-fixture.mjs +1 -0
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-link.mjs +1 -0
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-session.mjs +2 -0
  26. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-shapes.mjs +1 -0
  27. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board-slots.mjs +9 -1
  28. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-board.mjs +1 -0
  29. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ceremonies.mjs +1 -0
  30. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-connections.mjs +1 -0
  31. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-context.mjs +1 -0
  32. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-crypto.mjs +1 -0
  33. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +1 -0
  34. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-descriptor.mjs +2 -1
  35. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate-rules.mjs +1 -0
  36. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-estate.mjs +1 -0
  37. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-events.mjs +1 -0
  38. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-holds.mjs +1 -0
  39. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +1 -0
  40. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-hub.mjs +1 -0
  41. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-identifiers.mjs +1 -0
  42. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop-rules.mjs +1 -0
  43. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +1 -0
  44. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-jsvalue.mjs +1 -0
  45. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-load.mjs +1 -0
  46. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-lock.mjs +1 -0
  47. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-logs.mjs +1 -0
  48. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-mandate.mjs +1 -0
  49. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-openrouter.mjs +1 -0
  50. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-ops-digest.mjs +1 -0
  51. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package-schema.mjs +1 -0
  52. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +1 -0
  53. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-page-links.mjs +1 -0
  54. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-paths.mjs +1 -0
  55. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-peer-owner.mjs +2 -1
  56. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-platform.mjs +1 -0
  57. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-profiles.mjs +1 -0
  58. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -0
  59. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-secrets.mjs +1 -0
  60. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +1 -0
  61. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-share.mjs +1 -0
  62. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-socket-proof.mjs +1 -0
  63. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +15 -3
  64. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-tailnet-identity.mjs +1 -0
  65. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-tailnet.mjs +1 -0
  66. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-time.mjs +1 -0
  67. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-usage.mjs +1 -0
  68. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_a2a.py +1 -0
  69. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_a2a_server.py +1 -0
  70. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_actions.py +1 -0
  71. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_auth.py +1 -0
  72. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +1 -0
  73. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_base.py +1 -0
  74. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board.py +1 -0
  75. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_fixture.py +1 -0
  76. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_link.py +1 -0
  77. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_session.py +2 -0
  78. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_shapes.py +1 -0
  79. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_board_slots.py +10 -1
  80. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_ceremonies.py +1 -0
  81. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_connections.py +1 -0
  82. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_context.py +1 -0
  83. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_crypto.py +1 -0
  84. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +1 -0
  85. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_descriptor.py +2 -1
  86. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate.py +1 -0
  87. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_estate_rules.py +1 -0
  88. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_events.py +1 -0
  89. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_holds.py +1 -0
  90. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +1 -0
  91. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_hub.py +1 -0
  92. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_identifiers.py +1 -0
  93. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +1 -0
  94. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop_rules.py +1 -0
  95. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_jsvalue.py +1 -0
  96. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_load.py +1 -0
  97. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_lock.py +1 -0
  98. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_logs.py +1 -0
  99. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_mandate.py +1 -0
  100. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_openrouter.py +1 -0
  101. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_ops_digest.py +1 -0
  102. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package.py +1 -0
  103. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_package_schema.py +1 -0
  104. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_page_links.py +1 -0
  105. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_paths.py +1 -0
  106. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_peer_owner.py +47 -47
  107. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_platform.py +1 -0
  108. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_profiles.py +1 -0
  109. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -0
  110. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_secrets.py +1 -0
  111. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +1 -0
  112. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_share.py +1 -0
  113. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_socket_proof.py +1 -0
  114. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +16 -8
  115. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_tailnet.py +1 -0
  116. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_tailnet_identity.py +1 -0
  117. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_time.py +1 -0
  118. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_usage.py +1 -0
  119. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +321 -105
  120. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +2 -1
  121. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
  122. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/where-agents-run.md +2 -2
  123. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/scripts/admit.py +33 -13
  124. package/plugins/fabric-agent-adapter/skills/observing-products/SKILL.md +1 -1
  125. package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
  126. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.84.1 (2026-11-13)
4
+
5
+ 0.84.0 was tagged and not published: its release run failed one Node 18 test on the hosted floor runner.
6
+
7
+ ### Fixed
8
+
9
+ - **The board mandate's linear-time test reads bodies large enough to time** (FAA-135): at 64 KiB a read lasted under a
10
+ millisecond of CPU time, and one garbage collection made the 4x ratio read as 10x on Node 18; it now compares 256 KiB
11
+ with 1 MiB, where linear is still about 4 and quadratic about 16, and repeats each read until 50 ms of CPU time
12
+ (Windows counts it in 15.6 ms ticks, and one short read measured 0), in both twins' tests. No shipped code changes.
13
+
14
+ ## 0.84.0 (2026-11-13)
15
+
16
+ Wave 6 of the backlog sweep of 2026-11-12. The contract pin stays at `93e7db16` (`v0.1.0+2026-11-08.1`).
17
+
18
+ ### Changed
19
+
20
+ - **Every service kit module carries the package's licence as an SPDX line** (FAA-192 item 15, the operator's decision
21
+ of 2026-11-13): `AGPL-3.0-only OR LicenseRef-PassionCode-Commercial`, right after a shebang or as the first line, so
22
+ every copy `fabric_kit.py install` makes keeps it, an agent whose own files are all rights reserved included; the
23
+ kit's JSON schemas cannot carry a comment. `kit.json`'s digests change for every module. The dashboard kit moves to
24
+ 1.1.9 for the same line in its three copied files.
25
+ - **creating-fabric-agents names where an agent reads the private cloud Fabric-server template's repository, never the
26
+ repository** (FAA-192 item 1, the operator's decision of 2026-11-13): the instance's settings or the estate's agent
27
+ map.
28
+ - **`board.slot.returned` means one thing** (FAA-325): the reference service's take-back says `board.slot.taken_back`
29
+ (the slot still away), and the kit says `board.slot.returned` once the slot is held again, after a move back and now
30
+ also once an enroll or replace lands after the operator's take-back (once per take-back in the same process, both
31
+ twins); a take-back of a slot still held marks nothing.
32
+ - The supervisors' well-known reader uses the kit's one loopback rule (`fabric_socket_proof.loopback_host` /
33
+ `loopbackHost`): `127.1`, `2130706433`, `0x7f.1` and names under `.localhost` go on the checked connection (FAA-326).
34
+ - `fabric_peer_owner` no longer adds the kit folder to the host's `sys.path` (FAA-327): it asks the `fabric_socket_proof`
35
+ beside it, the host's imported module when that is the same file (one calibration in a process), else that file by
36
+ its path; a copy vendored alone keeps the table's answer, and every kit install that brings `fabric_peer_owner` still
37
+ brings `fabric_socket_proof`. `PEER_OWNER_VERSION` is `1.3.1+kit.8`.
38
+ - The supervisors' well-known reader refuses unread a loopback address the kit's rule does not take, with a zone
39
+ (`[::1%lo0]`) or IPv4-mapped (`[::ffff:127.0.0.1]`), where `urlopen` or `fetch` would reach the listener without the
40
+ owner check (0.84.0 seam reading).
41
+ - `test/validate.py` reads the private-terms list with the functions `admit.py` ships (`terms_file`, `terms_pattern`,
42
+ `term_lines`, `listed_files`), pinned to one case table; `admit.py`'s file listing no longer fails when `git` cannot
43
+ run (FAA-328).
44
+
45
+ ### Upgrading
46
+
47
+ - A dashboard or feed that reads `board.slot.returned` as the operator's take-back request reads
48
+ `board.slot.taken_back` now (FAA-325).
49
+
3
50
  ## 0.83.1 (2026-11-13)
4
51
 
5
52
  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). Start in
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.83.1",
3
+ "version": "0.84.1",
4
4
  "description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
5
5
  "scripts": {
6
6
  "test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
@@ -3,7 +3,7 @@
3
3
  "name": "fabric-agent-adapter",
4
4
  "displayName": "Fabric Agent Adapter",
5
5
  "description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks; and put an agent on a standing watch over a product (observer mode).",
6
- "version": "0.83.1",
6
+ "version": "0.84.1",
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.83.1"
12
+ version: "0.84.1"
13
13
  contract-version: "0.1.0"
14
14
  contract-commit: "93e7db164c7829e2783b4b7705c4113bb5201131"
15
15
  ---
@@ -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
@@ -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.83.1"
12
+ version: "0.84.1"
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.8 · Fabric's button (Fabric Agent Contract DEC-0040, FB-1…FB-8, FL-1…FL-6)
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.8';
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.8 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
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.8 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
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.8';
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 */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fabric-dashboard-kit",
3
- "version": "1.1.8",
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": "0c58c2758e780f4f520d3ea45d69a7d4221ad97cdc7e6999da7c7511e6beb96c",
19
- "fabric-dashboard.js": "dfaef6b91102817061f612aea1f4b5a85699a890d7f4fbda2780dc153f2e5da1",
20
- "fabric-button.js": "11ebad0cc598b09f034666be377caf0edc0042e9e86d7d8e8292dda57789be7f",
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. In the same board
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.returned` event (info, the capability as its subject) whose sentence says the route in
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`. The reference service adds `board.slot.returned` at a take-back.
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
@@ -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>`). Serve both same-origin and link them; nothing is inline:
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">
@@ -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.7`), 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, 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) |
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 |
@@ -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, `localhost`, `[::1]`) is read
59
- on a checked connection (FAA-257). `launchd_install` takes an injected reader, `fetch_well_known=` and
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
@@ -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
@@ -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
  //
@@ -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';
@@ -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';
@@ -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';
@@ -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)
@@ -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';
@@ -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
- if (this.slots[capability]?.state === 'moved') this.slots[capability] = { state: 'contested', renewedAt: 0 };
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) --
@@ -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.
@@ -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
@@ -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[].
@@ -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
@@ -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.
@@ -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
@@ -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.8';
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
 
@@ -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
@@ -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):
@@ -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';
@@ -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
@@ -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
  //
@@ -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
@@ -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;
@@ -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
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // The call queue and the load report of DEC-0104 (contract src/agent-network.ts, FAC-SEM-131 to FAC-SEM-133), as the
2
3
  // contract's reference answers them: a node that hosts a job-backed agent queues its jobs per (agentRef, context) with
3
4
  // these and reports its load as service-load/1 under extensions/load/0.1. Part of the Node service kit (FAA-289, layer
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // One copy of a service, locked before any side effect (LC-01, DEC-0057): the instance lock and the supervisor marker.
2
3
  // Part of the Node service kit (FAA-65, layer L3); the twin of fabric_lock.py. Node 20+ (22+ for the Linux lock), no dependency.
3
4
  //
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // Logs and stopping (LC-01, LC-12): a rotating log, a capped stdout log, the stop signal and the drain.
2
3
  // Part of the Node service kit (FAA-65, layer L3); the twin of fabric_logs.py. Node 20+, no dependency.
3
4
  import fs from 'node:fs';
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // The operator's mandate, mandate/1 (DEC-0125, FAC-SEM-144): the operator's instruction for one task travels with the
2
3
  // task, narrowed at each hand-over. Part of the Node service kit (layer L2); the twin of fabric_mandate.py.
3
4
  //
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // OpenRouter chat completions for a service: its own key, a spend ceiling checked before every attempt, a usage receipt
2
3
  // for every answered call, and a fallback model of another vendor. The twin of fabric_openrouter.py: the same rules, the
3
4
  // same cases (test/fixtures/kit-openrouter-cases.json); the rules are written out in that file's docstring.
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // A service's operations digests (contract DEC-0153, docs/specification/ops-digest.md at the pin): every record of its
2
3
  // operations log counted by operation and outcome in the hour it happened, one ops.digest.hourly@1 line for each hour
3
4
  // the service observed itself running in (an empty one included), and one ops.digest.daily@1 line for each closed UTC
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // fabric-package/1, the schema reading: the package schema bundled from the contract at the pin, read by a JSON
2
3
  // Schema 2020-12 subset with JavaScript's patterns, lengths in code points and the formats the contract uses.
3
4
  // fabric-package.mjs checks, packs, signs and verifies on it and re-exports schemaProblems. Part of the Node service
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
2
3
  // fabric-package/1 (contract DEC-0050, DEC-0051, DEC-0071, DEC-0074; FAA-27a): pack an agent or a skill set as one folder
3
4
  // with fabric.package.json, sign it, and verify it. The twin of fabric_package.py; both write the same bytes.
4
5
  //
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // A service's pages as Fabric Dashboards' open_link (Fabric Agent Contract DEC-0123, PL-1 to PL-4, FAC-SEM-143;
2
3
  // `src/page-link-rules.ts` at the pin): build and read the open_link, tell a raw local address, and the findings on a
3
4
  // link a document hands a person and on a URL-mode input request. The twin of fabric_page_links.py, held to the
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
1
2
  // Where a service's things live (fabric-service/0.1): the services directory, its data, config, logs and run dirs per OS, private dirs, atomic writes.
2
3
  // Part of the Node service kit (FAA-65, layer L1); the twin of fabric_paths.py. Node 20+, no dependency.
3
4
  import crypto from 'node:crypto';