@passioncode-ai/fabric-agent-adapter 0.41.0 → 0.43.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 +61 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +3 -3
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +3 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_layout.mjs +20 -5
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs +2 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs +13 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.schema.json +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py +2 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py +3 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +220 -10
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/share-registration.schema.json +2 -1
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/references/session-hooks.md +10 -3
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session.py +5 -0
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py +14 -0
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +18 -1
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mail.py +3 -0
- package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mcp.py +81 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.43.0 (2026-10-22)
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Pinned to contract `bfa9a67`** (FAA-95; the contract review, PR #137 and #138, DEC-0096 and DEC-0097). `c55f2d5`
|
|
8
|
+
(0.39.0 to 0.42.1) joins the supported revisions. Every vendored vector was regenerated from the contract's own
|
|
9
|
+
functions at the pin: new negative package fixtures, a `comms-complete` case and `fabric-connections` in the register.
|
|
10
|
+
- **A delegation chain names a partner only for a partner actor** (contract `src/delegation.ts` at `bfa9a67`): an actor
|
|
11
|
+
that carries `partner` beside `sub` is named by its `sub` in the verified `chain`, in both kits.
|
|
12
|
+
- **`fabric-connections/0.1` is in both protocol registers** (DEC-0096), so a `protocols` list naming it is read as
|
|
13
|
+
the contract reads it. The kits do not emit the extension yet (FAA-62).
|
|
14
|
+
- **The provider schema's MCP branches are read as `if`/`then`/`else`** (the contract review): the schema parity test
|
|
15
|
+
takes the URL pattern from `else` (a `oneOf` before); the pattern itself is unchanged. No kit code walked that `oneOf`.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **The kit's copy of `fabric-package.schema.json` carries DEC-0097's path pattern.** ECMAScript's `.` stops at U+2028
|
|
20
|
+
and U+2029, so the old pattern accepted `skills<U+2028>/../../etc/passwd`; any character is now `[\s\S]`. Both kits'
|
|
21
|
+
own package checks already refused these paths (0.41.0). `share-registration.schema.json` is regenerated at the pin.
|
|
22
|
+
- **The settings backup's secret-name patterns follow DEC-0097** in both kits (`[\s\S]+_` for `.+_`); no input reached
|
|
23
|
+
the difference, since table and column names refuse a line break first. A contract-gated test holds each twin's
|
|
24
|
+
regex to the pinned schema's pattern.
|
|
25
|
+
- **A guard holds the kit's vendored schemas to the pin:** `test_the_kit_schemas_carry_the_patterns_of_the_pinned_contract`
|
|
26
|
+
fails when a pattern in either copy is not a pattern of that schema's `$ref` closure at the pinned contract.
|
|
27
|
+
|
|
28
|
+
## 0.42.1 (2026-10-22)
|
|
29
|
+
|
|
30
|
+
The first published release of the 0.42 line: everything in 0.42.0 below, plus one test fix.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **`test/entry-points.test.mjs` on Windows.** The test that a layout report with no rule exits 2 imported the script
|
|
35
|
+
by its path; Windows reads `D:\...` in an import as a URL with the scheme `d:`. It imports a file URL now. The tag
|
|
36
|
+
`v0.42.0` stays as it was: its release run ([39771949538](https://github.com/passioncode-ai/fabric-agent-adapter/actions/runs/39771949538))
|
|
37
|
+
stopped at this test on the Windows job, so 0.42.0 was never published to npm or as a GitHub release.
|
|
38
|
+
|
|
39
|
+
## 0.42.0 (2026-10-22, tagged, not published)
|
|
40
|
+
|
|
41
|
+
The open asks of the Fabric project board, closed ([brief](docs/evidence/specs/2026-10-22-board-asks-0.42.0-brief.md)).
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **Session hooks follow Fabric 0.3.9** (board thread `02bf19c5`, FAA-93; Fabric's tracking audit TR-1, TR-2, TR-11).
|
|
46
|
+
The session-wide release carries `observedAt`, the time the end hook fired, where the release tool's input schema
|
|
47
|
+
names it, so Fabric refuses an end from before the session enrolled (`stale-end`). A `SessionEnd` with reason
|
|
48
|
+
`clear` releases nothing and observes no end: `/clear` keeps the agent process and its fabric-mcp; turns already
|
|
49
|
+
spooled still go out. An end followed by a later turn of the same session id is dropped with a log line instead of
|
|
50
|
+
being delivered to a resumed process (`claude --resume` keeps the id), which closes FAA-83. When
|
|
51
|
+
`fabric-mcp --rejoin-only` exits 3 (no session holds the id), the worker drops the spool, marks the folder and logs
|
|
52
|
+
it once; for 15 minutes the hooks spool nothing for that id, then one rejoin tries again.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **Kit scripts started through a symlinked folder ran nothing** (board thread `b42e16b7`, FAA-94).
|
|
57
|
+
`check_dashboard_layout.mjs` and `fabric-package.mjs` compared `import.meta.url` (resolved) with `process.argv[1]`
|
|
58
|
+
(the link), so under the launcher's `~/.passioncode/current` a layout check printed nothing and exited 0. Both
|
|
59
|
+
compare real paths now, and a layout report with no rule in it exits 2.
|
|
60
|
+
- **The kit history guard runs in hosted CI** (FAA-82). The `python` job checks out the full history with tags and sets
|
|
61
|
+
`FABRIC_REQUIRE_RELEASE_TAGS=1`, under which `test_a_released_version_keeps_its_digests` fails instead of skipping
|
|
62
|
+
when no release tag is present.
|
|
63
|
+
|
|
3
64
|
## 0.41.0 (2026-10-22)
|
|
4
65
|
|
|
5
66
|
The 2026-10-22 audit, closed (FAA-68 to FAA-81; [report](docs/reports/2026-10-22-adapter-audit/README.md),
|
package/README.md
CHANGED
|
@@ -274,7 +274,7 @@ Scaffolding is non-destructive by default. It writes only the paths declared in
|
|
|
274
274
|
The default pin for new bundles is [`fabric-contract.lock.json`](fabric-contract.lock.json):
|
|
275
275
|
|
|
276
276
|
- version: `0.1.0`
|
|
277
|
-
- commit: `
|
|
277
|
+
- commit: `bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0`
|
|
278
278
|
|
|
279
279
|
Every other mention of the default contract revision (this section, the skills' metadata, the
|
|
280
280
|
skill card, `adapt_project.py`) must equal it; `python3 test/validate.py` fails a tree
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "fabric-agent-adapter",
|
|
4
4
|
"displayName": "Fabric Agent Adapter",
|
|
5
5
|
"description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles; and teach a coding agent to work in a project through Fabric (fabric-mcp, fabric_whoami, claim and release), with Claude Code session hooks.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.43.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
9
9
|
"url": "https://passioncode.ai/"
|
|
@@ -5,9 +5,9 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
5
5
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.43.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Adapting projects to Fabric
|
|
@@ -76,7 +76,7 @@ Use exactly:
|
|
|
76
76
|
|
|
77
77
|
- contract version `0.1.0`;
|
|
78
78
|
- repository `https://github.com/passioncode-ai/fabric-agent-contract`;
|
|
79
|
-
- commit `
|
|
79
|
+
- commit `bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0`.
|
|
80
80
|
|
|
81
81
|
This is the default for new bundles. When checking an issued legacy bundle, preserve its
|
|
82
82
|
explicit supported lock and use that exact clean checkout. Never silently upgrade or
|
package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py
CHANGED
|
@@ -22,10 +22,10 @@ import fabric_secrets as _secrets # noqa: E402 - the contract's credential dete
|
|
|
22
22
|
|
|
23
23
|
CONTRACT_VERSION = "0.1.0"
|
|
24
24
|
CONTRACT_REPOSITORY = "https://github.com/passioncode-ai/fabric-agent-contract"
|
|
25
|
-
CONTRACT_COMMIT = "
|
|
25
|
+
CONTRACT_COMMIT = "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0"
|
|
26
26
|
# #region supported-contract-revisions — docs: README.md#contract-pin
|
|
27
27
|
# Only this declaration may name a legacy revision in live files.
|
|
28
|
-
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
28
|
+
SUPPORTED_CONTRACT_COMMITS = (CONTRACT_COMMIT, "c55f2d5a11c9a0197e958e87212fca7ae1154769", "07042181bfae2a481aa0da1a5651f24c76669c48", "d8146cfb0a1c74fc6432284c4356bb0c864b37b5", "82e163665e156a08aa3b92e4711015582c06162c", "1636fa97262f4a26e2086572d540c2ee701e0010", "f00a7685e3861c27f7899c033fb850a145a1708f", "a046f57cf46ea9e3da57ff8ce6a3ed4d26d8774b", "fe55fc67cba1a9e34a736da7d148d4fe2a8fbfa0", "b291bf09e0a9f9fd3c16cf540832cd021203b7d1", "0cacd08b0e95b6abf131eae1206b60792138bc3c", "2eb91c00e852d9c31d804310d38fad91589fcbac", "8e49fbd5fbbf230e32c1969cd24ac3c22422f0a5", "a83bec6b47776af688402c18efec507143061f68", "52da526d7cc1e063d74c5b520dbc03d0ace15246", "78b2da018d2c4bd9ac1bde1dc3b7f1a110a175f5", "623bf61358c339cb10297807b3f024b5d9f1f327", "23f9fda4c05f8a3852246ee98d4f2adf74ed0875", "9091d3d6606b0c4b5591a38c3674356a01fd7f55", "df55c8c54a23251342a7ee57ba95642b7eb39e61", "2ce392291c6668598d12cd38327e24696b5ca15c")
|
|
29
29
|
# #endregion supported-contract-revisions
|
|
30
30
|
INTEROP_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/interop/0.1"
|
|
31
31
|
MCP_REVISION = "2026-07-28"
|
|
@@ -14,10 +14,10 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
14
14
|
compatibility: Python 3.9+ or Node.js 20+ for the kits (Node.js 22+ for a Linux service's instance lock); the probe needs Python 3.9+. launchd steps are macOS-only; Linux services install a systemd user unit and Windows ones a per-user Scheduled Task with the kits' writers. Dashboard handoff optionally uses Fabric Dashboards MCP link/host_status/open; without it, report unresolved host capability. The contract checkout is optional.
|
|
15
15
|
metadata:
|
|
16
16
|
author: PassionCode.ai
|
|
17
|
-
version: "0.
|
|
17
|
+
version: "0.43.0"
|
|
18
18
|
contract-version: "0.1.0"
|
|
19
19
|
extension: "fabric-service/0.1"
|
|
20
|
-
extension-commit: "
|
|
20
|
+
extension-commit: "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0"
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# Building Fabric services
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# fabric-service/0.1: wire reference
|
|
2
2
|
|
|
3
|
-
Pinned to `fabric-agent-contract` commit `
|
|
3
|
+
Pinned to `fabric-agent-contract` commit `bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0`
|
|
4
4
|
(`docs/specification/service.md`, DEC-0015; the usage report DEC-0021; Windows and Linux supervision
|
|
5
5
|
DEC-0032 and DEC-0033; the operator channel DEC-0034 and DEC-0035; the embedded dashboard DEC-0036;
|
|
6
6
|
delegation and the operator session's lifetime DEC-0039; the meter's call window DEC-0041; session handoff DEC-0042;
|
|
@@ -8,7 +8,8 @@ canonical forms DEC-0043; `degraded[].setup` and `run.mcp.stdio.scope` DEC-0044;
|
|
|
8
8
|
DEC-0045; runner and model profiles DEC-0046; the estate record DEC-0055; one copy under any supervisor and its marker,
|
|
9
9
|
the Windows token-file reader DEC-0057; the hub key the estate certifies DEC-0060; signing credentials DEC-0063; the
|
|
10
10
|
estate record's 60 s skew DEC-0066; an app's own descriptor DEC-0069; the descriptor for listings DEC-0061; identifier equality
|
|
11
|
-
by normal form DEC-0076; the project board's directory page DEC-0077 and a replacement's transferred attempts DEC-0078; an operator's hold DEC-0079, a structured finding DEC-0080 and the owner's settlement DEC-0081
|
|
11
|
+
by normal form DEC-0076; the project board's directory page DEC-0077 and a replacement's transferred attempts DEC-0078; an operator's hold DEC-0079, a structured finding DEC-0080 and the owner's settlement DEC-0081; `fabric-connections/0.1` in the protocol register
|
|
12
|
+
DEC-0096; a schema pattern never uses a bare dot DEC-0097). The contract's schemas are normative;
|
|
12
13
|
this page is the working summary. Extension key:
|
|
13
14
|
`https://fabric.passioncode.ai/agent-contract/extensions/service/0.1`.
|
|
14
15
|
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
// scroll box) and ED-5 (sticky chrome within min(120 px, a quarter of the height), anchors landing
|
|
14
14
|
// below it, no nested full-height scroller). What it cannot measure is NOT_RUN with the reason,
|
|
15
15
|
// never a pass. WebKit is the default engine (Safari's). Exit 0 when nothing FAILs, 1 when
|
|
16
|
-
// something does, 2 on a usage error. It reads; it never clicks a control of the page.
|
|
17
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
16
|
+
// something does, 2 on a usage error or a report with no rule in it. It reads; it never clicks a control of the page.
|
|
17
|
+
import { readFileSync, existsSync, realpathSync } from 'node:fs';
|
|
18
18
|
import { createRequire } from 'node:module';
|
|
19
19
|
import { homedir, platform } from 'node:os';
|
|
20
20
|
import path from 'node:path';
|
|
21
|
-
import { pathToFileURL } from 'node:url';
|
|
21
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
22
22
|
|
|
23
23
|
const EXTENSION_KEY = 'https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1';
|
|
24
24
|
const RULES = ['ED-1', 'ED-2', 'ED-3', 'ED-4', 'ED-5'];
|
|
@@ -251,7 +251,7 @@ export function verdicts(width, floor, m) {
|
|
|
251
251
|
return rows;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
function report(rows, opts, target) {
|
|
254
|
+
export function report(rows, opts, target) {
|
|
255
255
|
rows = rows.map((r) => ({ ...r, evidence: scrub(r.evidence) }));
|
|
256
256
|
target = scrub(target);
|
|
257
257
|
const failed = rows.filter((r) => r.verdict === 'FAIL').length;
|
|
@@ -261,6 +261,10 @@ function report(rows, opts, target) {
|
|
|
261
261
|
for (const r of rows) process.stdout.write(`${r.verdict.padEnd(8)} ${(r.rule + (r.width ? '@' + r.width : '')).padEnd(10)} ${r.evidence}\n`);
|
|
262
262
|
process.stdout.write(`\n${rows.length} rule(s), ${failed} FAIL, ${rows.filter((r) => r.verdict === 'NOT_RUN').length} NOT_RUN\n`);
|
|
263
263
|
}
|
|
264
|
+
if (!rows.length) {
|
|
265
|
+
process.stderr.write('no rule ran: nothing was measured, so nothing passed\n');
|
|
266
|
+
return 2;
|
|
267
|
+
}
|
|
264
268
|
return failed ? 1 : 0;
|
|
265
269
|
}
|
|
266
270
|
|
|
@@ -319,6 +323,17 @@ async function main(argv) {
|
|
|
319
323
|
return report(rows, opts, shown);
|
|
320
324
|
}
|
|
321
325
|
|
|
322
|
-
|
|
326
|
+
// Whether node was started on this file. Real paths, not URLs: the launcher installs the plugin under a symlinked
|
|
327
|
+
// folder (~/.passioncode/current), and comparing import.meta.url (resolved) with argv[1] (the link) never ran main
|
|
328
|
+
// (board thread b42e16b7).
|
|
329
|
+
function startedDirectly() {
|
|
330
|
+
try {
|
|
331
|
+
return Boolean(process.argv[1]) && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
|
|
332
|
+
} catch {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (startedDirectly()) {
|
|
323
338
|
main(process.argv.slice(2)).then((code) => process.exit(code), (err) => { process.stderr.write(String(err?.stack || err) + '\n'); process.exit(2); });
|
|
324
339
|
}
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-backups.mjs
CHANGED
|
@@ -18,11 +18,11 @@ export const SETTINGS_BACKUP_MAX_AGE_SECONDS = 24 * 60 * 60;
|
|
|
18
18
|
|
|
19
19
|
const TABLE = /^[a-z][a-z0-9_]{0,62}$/;
|
|
20
20
|
|
|
21
|
-
const SECRET_TABLE = /^((
|
|
21
|
+
const SECRET_TABLE = /^(([\s\S]+_)?(account_connections?|account_connection_drafts?|tokens?|secrets?|credentials?|passwords?|login_codes?)|(operator_)?sessions?)$/;
|
|
22
22
|
|
|
23
23
|
const COLUMN = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/;
|
|
24
24
|
|
|
25
|
-
const SECRET_COLUMN = /^(
|
|
25
|
+
const SECRET_COLUMN = /^(?:[\s\S]+_)?(?:[Tt]oken|[Ss]ecret|[Pp]assword|[Pp]assphrase|[Aa]pi_?[Kk]ey|[Pp]rivate_[Kk]ey|[Cc]ookie|[Ll]ogin_[Cc]ode|[Oo]tp|[Cc]redential)s?$/;
|
|
26
26
|
|
|
27
27
|
const REASON = /^[a-z][a-z0-9_.-]{0,63}$/;
|
|
28
28
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-delegation.mjs
CHANGED
|
@@ -188,7 +188,8 @@ export function chainDepth(act) {
|
|
|
188
188
|
|
|
189
189
|
function chainOf(act) {
|
|
190
190
|
const chain = [];
|
|
191
|
-
|
|
191
|
+
// The contract's chainOf at bfa9a67: a node names its partner only when it is a partner actor (the partner member alone).
|
|
192
|
+
for (let node = act; node; node = 'act' in node ? node.act : undefined) chain.push(isPartnerActor(node) ? node.partner : node.sub);
|
|
192
193
|
return chain;
|
|
193
194
|
}
|
|
194
195
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-package.mjs
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import crypto from 'node:crypto';
|
|
16
16
|
import fs from 'node:fs';
|
|
17
17
|
import path from 'node:path';
|
|
18
|
-
import { fileURLToPath
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
19
|
import { isSmallOrderKey, jcs } from './fabric-delegation.mjs';
|
|
20
20
|
import { secretArgument, secretValue } from './fabric-secrets.mjs';
|
|
21
21
|
|
|
@@ -701,4 +701,15 @@ export function main(argv, print = (line) => process.stdout.write(`${line}\n`))
|
|
|
701
701
|
return answer.ok ? 0 : 1;
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
-
|
|
704
|
+
// Whether node was started on this file. Real paths, not URLs: the launcher installs the plugin under a symlinked
|
|
705
|
+
// folder (~/.passioncode/current), and comparing import.meta.url (resolved) with argv[1] (the link) never ran main
|
|
706
|
+
// (board thread b42e16b7).
|
|
707
|
+
function startedDirectly() {
|
|
708
|
+
try {
|
|
709
|
+
return Boolean(process.argv[1]) && fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(import.meta.url));
|
|
710
|
+
} catch {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (startedDirectly()) process.exitCode = main(process.argv.slice(2));
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
},
|
|
558
558
|
"path": {
|
|
559
559
|
"type": "string",
|
|
560
|
-
"pattern": "^(?![/~])(
|
|
560
|
+
"pattern": "^(?![/~])(?![\\s\\S]*\\\\)(?![\\s\\S]*//)(?!(?:[\\s\\S]*/)?\\.{1,2}(?:/|$))[^\\u0000-\\u001f:]{1,256}(?<!/)$"
|
|
561
561
|
},
|
|
562
562
|
"common.$defs.semver": {
|
|
563
563
|
"type": "string",
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-protocols.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { credentialName, secretArgument, secretUrl, secretValue } from './fabric
|
|
|
8
8
|
/** Each contract protocol's published revisions, oldest first (the contract's `PROTOCOL_REVISIONS`); a test holds it equal to the contract's. */
|
|
9
9
|
export const PROTOCOL_REVISIONS = new Map(Object.entries({
|
|
10
10
|
'access-log': ['1'], approval: ['1'], 'activity-summary': ['1'], 'coding-agents': ['1'], 'enroll-token': ['1'], entitlement: ['1'], 'entitlement-key-set': ['1'], 'estate-record': ['1'], 'execution-packet': ['1'],
|
|
11
|
-
'fabric-activity': ['0.1'], 'fabric-dashboard': ['0.1'], 'fabric-delegation': ['0.1'], 'fabric-device': ['0.1'],
|
|
11
|
+
'fabric-activity': ['0.1'], 'fabric-connections': ['0.1'], 'fabric-dashboard': ['0.1'], 'fabric-delegation': ['0.1'], 'fabric-device': ['0.1'],
|
|
12
12
|
'fabric-interop': ['0.1', '0.2'], 'fabric-local-channel': ['0.1'], 'fabric-local-runner': ['0.1'], 'fabric-operator-channel': ['0.1'],
|
|
13
13
|
'fabric-package': ['1'], 'fabric-project-comms': ['0.1'], 'fabric-proposal': ['1'], 'fabric-provider': ['0.1'], 'fabric-relay': ['0.1'],
|
|
14
14
|
'fabric-secret-envelope': ['1'], 'fabric-service': ['0.1'], 'fabric-settings-backup': ['1'], heartbeat: ['1'], 'learning-note': ['1'],
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_backups.py
CHANGED
|
@@ -49,13 +49,13 @@ _SAFE_INTEGER = 2 ** 53 - 1
|
|
|
49
49
|
_TABLE = re.compile(r"^[a-z][a-z0-9_]{0,62}\Z")
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
_SECRET_TABLE = re.compile(r"^((
|
|
52
|
+
_SECRET_TABLE = re.compile(r"^(([\s\S]+_)?(account_connections?|account_connection_drafts?|tokens?|secrets?|credentials?|passwords?|login_codes?)|(operator_)?sessions?)\Z")
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
_COLUMN = re.compile(r"^[A-Za-z_][A-Za-z0-9_]{0,62}\Z")
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
_SECRET_COLUMN = re.compile(r"^(
|
|
58
|
+
_SECRET_COLUMN = re.compile(r"^(?:[\s\S]+_)?(?:[Tt]oken|[Ss]ecret|[Pp]assword|[Pp]assphrase|[Aa]pi_?[Kk]ey|[Pp]rivate_[Kk]ey|[Cc]ookie|[Ll]ogin_[Cc]ode|[Oo]tp|[Cc]redential)s?\Z")
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
_REASON = re.compile(r"^[a-z][a-z0-9_.-]{0,63}\Z")
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_delegation.py
CHANGED
|
@@ -284,7 +284,9 @@ def _chain_of(act: Dict[str, Any]) -> List[str]:
|
|
|
284
284
|
chain = []
|
|
285
285
|
node: Any = act
|
|
286
286
|
while isinstance(node, dict):
|
|
287
|
-
|
|
287
|
+
# The contract's chainOf at bfa9a67: a node names its partner only when it is a partner actor (the partner member
|
|
288
|
+
# alone); one that carries `partner` beside `sub` names its `sub`.
|
|
289
|
+
chain.append(node["partner"] if is_partner_actor(node) else node["sub"])
|
|
288
290
|
node = node.get("act")
|
|
289
291
|
return chain
|
|
290
292
|
|
package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_protocols.py
CHANGED
|
@@ -15,7 +15,7 @@ if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from
|
|
|
15
15
|
PROTOCOL_REVISIONS: Dict[str, Tuple[str, ...]] = {
|
|
16
16
|
"access-log": ("1",), "approval": ("1",), "activity-summary": ("1",), "coding-agents": ("1",), "enroll-token": ("1",), "entitlement": ("1",),
|
|
17
17
|
"entitlement-key-set": ("1",), "estate-record": ("1",), "execution-packet": ("1",),
|
|
18
|
-
"fabric-activity": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
18
|
+
"fabric-activity": ("0.1",), "fabric-connections": ("0.1",), "fabric-dashboard": ("0.1",), "fabric-delegation": ("0.1",), "fabric-device": ("0.1",),
|
|
19
19
|
"fabric-interop": ("0.1", "0.2"), "fabric-local-channel": ("0.1",), "fabric-local-runner": ("0.1",),
|
|
20
20
|
"fabric-operator-channel": ("0.1",), "fabric-package": ("1",), "fabric-project-comms": ("0.1",), "fabric-proposal": ("1",),
|
|
21
21
|
"fabric-provider": ("0.1",), "fabric-relay": ("0.1",), "fabric-secret-envelope": ("1",), "fabric-service": ("0.1",),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabric-service-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"about": "The service kit's modules in dependency order: a module imports only modules listed before it. Written by fabric_kit.py build; edit the order and layers by hand, never the digests.",
|
|
5
5
|
"python": [
|
|
6
6
|
{
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"fabric_estate",
|
|
63
63
|
"fabric_jsvalue"
|
|
64
64
|
],
|
|
65
|
-
"sha256": "
|
|
65
|
+
"sha256": "350e30cc0fb527bce1739c5f96bb9bec9028144def9d1b2630d1478529f8f996"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"module": "fabric_share",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"imports": [
|
|
140
140
|
"fabric_secrets"
|
|
141
141
|
],
|
|
142
|
-
"sha256": "
|
|
142
|
+
"sha256": "71482284e57334b2d364a44596fc4183baddfe61a80083d3099b7ef423dc6f38"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"module": "fabric_lock",
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
"fabric_paths",
|
|
175
175
|
"fabric_usage"
|
|
176
176
|
],
|
|
177
|
-
"sha256": "
|
|
177
|
+
"sha256": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb"
|
|
178
178
|
},
|
|
179
179
|
{
|
|
180
180
|
"module": "fabric_descriptor",
|
|
@@ -424,7 +424,7 @@
|
|
|
424
424
|
"fabric-estate",
|
|
425
425
|
"fabric-jsvalue"
|
|
426
426
|
],
|
|
427
|
-
"sha256": "
|
|
427
|
+
"sha256": "2bc4310c6c7f0f6a11ba29d8bad2341feb0e0285758c33080e879e0a3a5cf128"
|
|
428
428
|
},
|
|
429
429
|
{
|
|
430
430
|
"module": "fabric-share",
|
|
@@ -461,7 +461,7 @@
|
|
|
461
461
|
"fabric-jsvalue",
|
|
462
462
|
"fabric-secrets"
|
|
463
463
|
],
|
|
464
|
-
"sha256": "
|
|
464
|
+
"sha256": "34590076b2c6939b2892e86ed24b62cc5973315ec7a322de19c553336b049bf2",
|
|
465
465
|
"data": [
|
|
466
466
|
"fabric-package.schema.json"
|
|
467
467
|
]
|
|
@@ -499,7 +499,7 @@
|
|
|
499
499
|
"imports": [
|
|
500
500
|
"fabric-secrets"
|
|
501
501
|
],
|
|
502
|
-
"sha256": "
|
|
502
|
+
"sha256": "0ecc3c19bb0bd0393ff3a9ec503034e0ab251eaaf0254edf353e15d1b561f761"
|
|
503
503
|
},
|
|
504
504
|
{
|
|
505
505
|
"module": "fabric-lock",
|
|
@@ -534,7 +534,7 @@
|
|
|
534
534
|
"fabric-protocols",
|
|
535
535
|
"fabric-usage"
|
|
536
536
|
],
|
|
537
|
-
"sha256": "
|
|
537
|
+
"sha256": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005"
|
|
538
538
|
},
|
|
539
539
|
{
|
|
540
540
|
"module": "fabric-descriptor",
|
|
@@ -1612,10 +1612,220 @@
|
|
|
1612
1612
|
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
1613
1613
|
"fabric-package.schema.json": "6b688152984e294b806ffaf3483e6fa2e55cd0d9205bb5cba85f646868d90d58",
|
|
1614
1614
|
"share-registration.schema.json": "82ef3e8703dd6653b84ba9fdbaec2f366e062596da981b1823be3804fcb65b90"
|
|
1615
|
+
},
|
|
1616
|
+
"0.42.0": {
|
|
1617
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
1618
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
1619
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
1620
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
1621
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
1622
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
1623
|
+
"fabric_delegation.py": "92ff745fb76ebb5856f9bb55f7c46936035f1ae836056c71065b7bb6276b35e7",
|
|
1624
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
1625
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
1626
|
+
"fabric_package.py": "09e5b4d20564ccb318f5a5e4f33df0359873fa8239cf4f5fcd21c8af481fd211",
|
|
1627
|
+
"fabric_base.py": "684533b3a2aa3acd9b9e645a7a443427d279408f9f12f13456a0a991d57954ce",
|
|
1628
|
+
"fabric_platform.py": "8b0cd89193bc55da204a4a1850665c96929c6778523a8715b8156c5643745288",
|
|
1629
|
+
"fabric_paths.py": "0d87e572bde2b930391b27aa370d808e093ce45cfba6148706f5318219906d30",
|
|
1630
|
+
"fabric_protocols.py": "9f418eef2d64796067d213f36a967978486e632c9acac50e216dd22cb898216c",
|
|
1631
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
1632
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
1633
|
+
"fabric_backups.py": "ce042e49fc32600ef81d550603b4655153a1c4b13520b1edc04b9b9f358f4b91",
|
|
1634
|
+
"fabric_descriptor.py": "43c59437502a1af6c6305f0d4dddfbb9e616e81441d6ad7137f9d96b7a918a06",
|
|
1635
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
1636
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
1637
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
1638
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
1639
|
+
"fabric_service.py": "3c8f69e139ee6fe714cad78c30de1a076ac7fbf9f7f419cd2cd131e95d889f6a",
|
|
1640
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
1641
|
+
"fabric_interop.py": "67a78026ad434bb638c8230b6bfadc9cbe67561842ae7493c77d912855f38d61",
|
|
1642
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
1643
|
+
"fabric_board_shapes.py": "a8daefdc9283219206875b5d964b49552b6b3ba7e69c925abe08a44afc91c234",
|
|
1644
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
1645
|
+
"fabric_board_session.py": "878ceed970a84087a320fd8eb971c210613a0fa2c524b68793fb32042910581e",
|
|
1646
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
1647
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
1648
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
1649
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
1650
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
1651
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
1652
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
1653
|
+
"fabric-secrets.mjs": "2f7baaebfd08daf8b9c9ae1b75ba8ca04997d9dbf113897b4fb1464391c2d66d",
|
|
1654
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
1655
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
1656
|
+
"fabric-delegation.mjs": "c27c84aca9d0374c8930eabc82b8c5d2ad66b3a936d7cff324ddd49dbd1f9618",
|
|
1657
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
1658
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
1659
|
+
"fabric-package.mjs": "34590076b2c6939b2892e86ed24b62cc5973315ec7a322de19c553336b049bf2",
|
|
1660
|
+
"fabric-base.mjs": "17a92f5e9b71a855648e39e06388bad7f1b969605bd7b1f534ddf67b41a2fb5d",
|
|
1661
|
+
"fabric-platform.mjs": "1349e3638c21caf7da7937ef6a5dfeefe05a8ee733520f0d581624095efeb388",
|
|
1662
|
+
"fabric-paths.mjs": "e6f5e2ce7c8e7a1452d6ee69977489f4c09ca6f1d3100df9c303274f0b7b16b1",
|
|
1663
|
+
"fabric-protocols.mjs": "45277a794ef40f37599b25dd6ceebc3fa3e60a4cd51caf33e56e48eba8600920",
|
|
1664
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
1665
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
1666
|
+
"fabric-backups.mjs": "c504b4ce85b8ed1e926683da93a70693fd8d23a7935f9b57c950e24304a0fa92",
|
|
1667
|
+
"fabric-descriptor.mjs": "b9304be4cba4fedddc6a0da83eef861f045691c8309ff614a5522946af4069b0",
|
|
1668
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
1669
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
1670
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
1671
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
1672
|
+
"fabric-service.mjs": "fd31188c1709b0cebbcea995fc817ad7b6ad4fe21f2af12f65d001309f6baacc",
|
|
1673
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
1674
|
+
"fabric-interop.mjs": "81c0b09045ada54f6645f40d935c0de06119793631b3240b1a613f4f2afd9d84",
|
|
1675
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
1676
|
+
"fabric-board-shapes.mjs": "ad1094397540862b104d9317d6902031d35e64b16c12bf849fb883e12cb78d45",
|
|
1677
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
1678
|
+
"fabric-board-session.mjs": "744a8c9a518c27f2ddfd20b1b22afebc3ccc4f59aeeb7a38d7c12c2ddcae158d",
|
|
1679
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
1680
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
1681
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
1682
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
1683
|
+
"fabric-package.schema.json": "6b688152984e294b806ffaf3483e6fa2e55cd0d9205bb5cba85f646868d90d58",
|
|
1684
|
+
"share-registration.schema.json": "82ef3e8703dd6653b84ba9fdbaec2f366e062596da981b1823be3804fcb65b90"
|
|
1685
|
+
},
|
|
1686
|
+
"0.42.1": {
|
|
1687
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
1688
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
1689
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
1690
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
1691
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
1692
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
1693
|
+
"fabric_delegation.py": "92ff745fb76ebb5856f9bb55f7c46936035f1ae836056c71065b7bb6276b35e7",
|
|
1694
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
1695
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
1696
|
+
"fabric_package.py": "09e5b4d20564ccb318f5a5e4f33df0359873fa8239cf4f5fcd21c8af481fd211",
|
|
1697
|
+
"fabric_base.py": "684533b3a2aa3acd9b9e645a7a443427d279408f9f12f13456a0a991d57954ce",
|
|
1698
|
+
"fabric_platform.py": "8b0cd89193bc55da204a4a1850665c96929c6778523a8715b8156c5643745288",
|
|
1699
|
+
"fabric_paths.py": "0d87e572bde2b930391b27aa370d808e093ce45cfba6148706f5318219906d30",
|
|
1700
|
+
"fabric_protocols.py": "9f418eef2d64796067d213f36a967978486e632c9acac50e216dd22cb898216c",
|
|
1701
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
1702
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
1703
|
+
"fabric_backups.py": "ce042e49fc32600ef81d550603b4655153a1c4b13520b1edc04b9b9f358f4b91",
|
|
1704
|
+
"fabric_descriptor.py": "43c59437502a1af6c6305f0d4dddfbb9e616e81441d6ad7137f9d96b7a918a06",
|
|
1705
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
1706
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
1707
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
1708
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
1709
|
+
"fabric_service.py": "3c8f69e139ee6fe714cad78c30de1a076ac7fbf9f7f419cd2cd131e95d889f6a",
|
|
1710
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
1711
|
+
"fabric_interop.py": "67a78026ad434bb638c8230b6bfadc9cbe67561842ae7493c77d912855f38d61",
|
|
1712
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
1713
|
+
"fabric_board_shapes.py": "a8daefdc9283219206875b5d964b49552b6b3ba7e69c925abe08a44afc91c234",
|
|
1714
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
1715
|
+
"fabric_board_session.py": "878ceed970a84087a320fd8eb971c210613a0fa2c524b68793fb32042910581e",
|
|
1716
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
1717
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
1718
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
1719
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
1720
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
1721
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
1722
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
1723
|
+
"fabric-secrets.mjs": "2f7baaebfd08daf8b9c9ae1b75ba8ca04997d9dbf113897b4fb1464391c2d66d",
|
|
1724
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
1725
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
1726
|
+
"fabric-delegation.mjs": "c27c84aca9d0374c8930eabc82b8c5d2ad66b3a936d7cff324ddd49dbd1f9618",
|
|
1727
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
1728
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
1729
|
+
"fabric-package.mjs": "34590076b2c6939b2892e86ed24b62cc5973315ec7a322de19c553336b049bf2",
|
|
1730
|
+
"fabric-base.mjs": "17a92f5e9b71a855648e39e06388bad7f1b969605bd7b1f534ddf67b41a2fb5d",
|
|
1731
|
+
"fabric-platform.mjs": "1349e3638c21caf7da7937ef6a5dfeefe05a8ee733520f0d581624095efeb388",
|
|
1732
|
+
"fabric-paths.mjs": "e6f5e2ce7c8e7a1452d6ee69977489f4c09ca6f1d3100df9c303274f0b7b16b1",
|
|
1733
|
+
"fabric-protocols.mjs": "45277a794ef40f37599b25dd6ceebc3fa3e60a4cd51caf33e56e48eba8600920",
|
|
1734
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
1735
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
1736
|
+
"fabric-backups.mjs": "c504b4ce85b8ed1e926683da93a70693fd8d23a7935f9b57c950e24304a0fa92",
|
|
1737
|
+
"fabric-descriptor.mjs": "b9304be4cba4fedddc6a0da83eef861f045691c8309ff614a5522946af4069b0",
|
|
1738
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
1739
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
1740
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
1741
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
1742
|
+
"fabric-service.mjs": "fd31188c1709b0cebbcea995fc817ad7b6ad4fe21f2af12f65d001309f6baacc",
|
|
1743
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
1744
|
+
"fabric-interop.mjs": "81c0b09045ada54f6645f40d935c0de06119793631b3240b1a613f4f2afd9d84",
|
|
1745
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
1746
|
+
"fabric-board-shapes.mjs": "ad1094397540862b104d9317d6902031d35e64b16c12bf849fb883e12cb78d45",
|
|
1747
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
1748
|
+
"fabric-board-session.mjs": "744a8c9a518c27f2ddfd20b1b22afebc3ccc4f59aeeb7a38d7c12c2ddcae158d",
|
|
1749
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
1750
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
1751
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
1752
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
1753
|
+
"fabric-package.schema.json": "6b688152984e294b806ffaf3483e6fa2e55cd0d9205bb5cba85f646868d90d58",
|
|
1754
|
+
"share-registration.schema.json": "82ef3e8703dd6653b84ba9fdbaec2f366e062596da981b1823be3804fcb65b90"
|
|
1755
|
+
},
|
|
1756
|
+
"0.43.0": {
|
|
1757
|
+
"fabric_jsvalue.py": "0cd4eab0a5d6ae35d097f7c59a08dc29173cb61c561c49e5291a8dad15d36779",
|
|
1758
|
+
"fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
|
|
1759
|
+
"fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
|
|
1760
|
+
"fabric_secrets.py": "68a0b5e9e90c468ec9ac67b2f0fd1848e08813d6ec1ec14a2a47337eb1a98911",
|
|
1761
|
+
"fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
|
|
1762
|
+
"fabric_estate.py": "50cc12166a00b680ba5b2e458200912d7bcfbef70bd73ec4edf57c7fcfa9b687",
|
|
1763
|
+
"fabric_delegation.py": "350e30cc0fb527bce1739c5f96bb9bec9028144def9d1b2630d1478529f8f996",
|
|
1764
|
+
"fabric_share.py": "78506fe1a60829c525dbf6266a0aa0749a2164290ed94da8249a20b4e9be5605",
|
|
1765
|
+
"fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
|
|
1766
|
+
"fabric_package.py": "09e5b4d20564ccb318f5a5e4f33df0359873fa8239cf4f5fcd21c8af481fd211",
|
|
1767
|
+
"fabric_base.py": "684533b3a2aa3acd9b9e645a7a443427d279408f9f12f13456a0a991d57954ce",
|
|
1768
|
+
"fabric_platform.py": "8b0cd89193bc55da204a4a1850665c96929c6778523a8715b8156c5643745288",
|
|
1769
|
+
"fabric_paths.py": "0d87e572bde2b930391b27aa370d808e093ce45cfba6148706f5318219906d30",
|
|
1770
|
+
"fabric_protocols.py": "71482284e57334b2d364a44596fc4183baddfe61a80083d3099b7ef423dc6f38",
|
|
1771
|
+
"fabric_lock.py": "ba2399d2137c7a7791b7133b9db9cca36693f4eb7e30955b25a75ade814e95ba",
|
|
1772
|
+
"fabric_usage.py": "ce685cb9fdfd62ea75fff8b1b2be12a2ba758da783e4bfb4dcebe47bcbeb832b",
|
|
1773
|
+
"fabric_backups.py": "02dc5eb66ec956723d3ddba07b6dd15f6a9726d901f4d60edfd02eee57880ceb",
|
|
1774
|
+
"fabric_descriptor.py": "43c59437502a1af6c6305f0d4dddfbb9e616e81441d6ad7137f9d96b7a918a06",
|
|
1775
|
+
"fabric_auth.py": "55794587750f6c9f40935b74295d83d7096cb4b26a0b36ac292334cd87d8f853",
|
|
1776
|
+
"fabric_events.py": "0086886c2c29dbd5c9d152be9d375c5bdf4a29f89b8095baff8490c2bcd64e47",
|
|
1777
|
+
"fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
|
|
1778
|
+
"fabric_supervisors.py": "a2dbf15aa1c4eb9de42996b413103fa4814afd2e4e66d1ab7315f30e06ab6841",
|
|
1779
|
+
"fabric_service.py": "3c8f69e139ee6fe714cad78c30de1a076ac7fbf9f7f419cd2cd131e95d889f6a",
|
|
1780
|
+
"fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
|
|
1781
|
+
"fabric_interop.py": "67a78026ad434bb638c8230b6bfadc9cbe67561842ae7493c77d912855f38d61",
|
|
1782
|
+
"fabric_hub.py": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a",
|
|
1783
|
+
"fabric_board_shapes.py": "a8daefdc9283219206875b5d964b49552b6b3ba7e69c925abe08a44afc91c234",
|
|
1784
|
+
"fabric_board_link.py": "b5bff994cb615c6a4bb0d88d020e3a59504166180e1fa1aea3be93224f2aeccb",
|
|
1785
|
+
"fabric_board_session.py": "878ceed970a84087a320fd8eb971c210613a0fa2c524b68793fb32042910581e",
|
|
1786
|
+
"fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
|
|
1787
|
+
"fabric_board.py": "0f075894b3e352194fcaf3fc7d08dee4e9f1c215e859769ed85fa5010e4a1599",
|
|
1788
|
+
"fabric_http.py": "5d7f72af3a73fdbe8c1f487ecf60cef23a7c46289eba542b03aff4706b8218d4",
|
|
1789
|
+
"fabric_openrouter.py": "2017d898c17001d7275f58267de653be7ecf6acd17ad8d9b24ecb7a43e5617d4",
|
|
1790
|
+
"fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
|
|
1791
|
+
"fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
|
|
1792
|
+
"fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
|
|
1793
|
+
"fabric-secrets.mjs": "2f7baaebfd08daf8b9c9ae1b75ba8ca04997d9dbf113897b4fb1464391c2d66d",
|
|
1794
|
+
"fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
|
|
1795
|
+
"fabric-estate.mjs": "912b1ceab57ed20f946986bf14ae2faf41fb8ea539e818164496874f3749ef65",
|
|
1796
|
+
"fabric-delegation.mjs": "2bc4310c6c7f0f6a11ba29d8bad2341feb0e0285758c33080e879e0a3a5cf128",
|
|
1797
|
+
"fabric-share.mjs": "d40a7405d7bd4c3213ed691330b7549afe8e023db0753b582e249714e672010d",
|
|
1798
|
+
"fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
|
|
1799
|
+
"fabric-package.mjs": "34590076b2c6939b2892e86ed24b62cc5973315ec7a322de19c553336b049bf2",
|
|
1800
|
+
"fabric-base.mjs": "17a92f5e9b71a855648e39e06388bad7f1b969605bd7b1f534ddf67b41a2fb5d",
|
|
1801
|
+
"fabric-platform.mjs": "1349e3638c21caf7da7937ef6a5dfeefe05a8ee733520f0d581624095efeb388",
|
|
1802
|
+
"fabric-paths.mjs": "e6f5e2ce7c8e7a1452d6ee69977489f4c09ca6f1d3100df9c303274f0b7b16b1",
|
|
1803
|
+
"fabric-protocols.mjs": "0ecc3c19bb0bd0393ff3a9ec503034e0ab251eaaf0254edf353e15d1b561f761",
|
|
1804
|
+
"fabric-lock.mjs": "ac219ab0a326d5c43c7c4c255e0c3843d4794de795a60e3af661e7d5350ea052",
|
|
1805
|
+
"fabric-usage.mjs": "e413569620bbc8221bc59e24b27e22d1483825ed18457801ed58d54a57de8114",
|
|
1806
|
+
"fabric-backups.mjs": "849acdc6eba0fff648c8158e61f6b68cccd7bedf0880f7d5ec03a6a20f1e7005",
|
|
1807
|
+
"fabric-descriptor.mjs": "b9304be4cba4fedddc6a0da83eef861f045691c8309ff614a5522946af4069b0",
|
|
1808
|
+
"fabric-auth.mjs": "3ea6796470fcd829bc72a772fb7e4c37532a09d1e37ff41592dcf1a1a3074ca2",
|
|
1809
|
+
"fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
|
|
1810
|
+
"fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
|
|
1811
|
+
"fabric-supervisors.mjs": "9d61c1a17538a5e2453e33e5ae347337336748041bc054478a96dd51f3d4fc51",
|
|
1812
|
+
"fabric-service.mjs": "fd31188c1709b0cebbcea995fc817ad7b6ad4fe21f2af12f65d001309f6baacc",
|
|
1813
|
+
"fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
|
|
1814
|
+
"fabric-interop.mjs": "81c0b09045ada54f6645f40d935c0de06119793631b3240b1a613f4f2afd9d84",
|
|
1815
|
+
"fabric-hub.mjs": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070",
|
|
1816
|
+
"fabric-board-shapes.mjs": "ad1094397540862b104d9317d6902031d35e64b16c12bf849fb883e12cb78d45",
|
|
1817
|
+
"fabric-board-link.mjs": "4cd6d4e21713a38c8e56f7d59db3148638b8c27c08e774d96a0f6283c6049e0a",
|
|
1818
|
+
"fabric-board-session.mjs": "744a8c9a518c27f2ddfd20b1b22afebc3ccc4f59aeeb7a38d7c12c2ddcae158d",
|
|
1819
|
+
"fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
|
|
1820
|
+
"fabric-board.mjs": "9e7bfe4d412521982224ef12bebfc2ff255eeeaf8d96cf40234ac18de68e7a59",
|
|
1821
|
+
"fabric-http.mjs": "f886bcb49c4353d039387ac9568738dda26697a94dd07fc6a6204500f0bc27bf",
|
|
1822
|
+
"fabric-openrouter.mjs": "f8f0168691f968b7cd85f36aa98e2167e88cc44f1104ff514fd0c7699b339253",
|
|
1823
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
1824
|
+
"share-registration.schema.json": "0df979d5973809d194723b23a0d18e520d9f1badc0f4a9e557aa33cbe7bc2922"
|
|
1615
1825
|
}
|
|
1616
1826
|
},
|
|
1617
1827
|
"data": {
|
|
1618
|
-
"fabric-package.schema.json": "
|
|
1619
|
-
"share-registration.schema.json": "
|
|
1828
|
+
"fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
|
|
1829
|
+
"share-registration.schema.json": "0df979d5973809d194723b23a0d18e520d9f1badc0f4a9e557aa33cbe7bc2922"
|
|
1620
1830
|
}
|
|
1621
1831
|
}
|
|
@@ -200,7 +200,8 @@
|
|
|
200
200
|
},
|
|
201
201
|
"sha256": {
|
|
202
202
|
"type": "string",
|
|
203
|
-
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
203
|
+
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
204
|
+
"description": "A content hash: sha256: and 64 lower-case hex digits. The bare 64-digit form, without the prefix, is sha256Hex."
|
|
204
205
|
},
|
|
205
206
|
"shareGrantId": {
|
|
206
207
|
"type": "string",
|
|
@@ -5,9 +5,9 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
|
|
|
5
5
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode. Ships in one plugin with adapting-projects-to-fabric, whose scripts it reuses.
|
|
6
6
|
metadata:
|
|
7
7
|
author: PassionCode.ai
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.43.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Creating Fabric-compatible agents
|
|
@@ -136,7 +136,7 @@ python3 <plugin-dir>/skills/adapting-projects-to-fabric/scripts/adapt_project.py
|
|
|
136
136
|
The effect class is declared, never defaulted: ask the author what the agent does outside itself when the request
|
|
137
137
|
does not say. Cost presets are only for a run whose cost varies; their amounts come from the author or measured runs.
|
|
138
138
|
|
|
139
|
-
Pin exactly contract `0.1.0` at commit `
|
|
139
|
+
Pin exactly contract `0.1.0` at commit `bfa9a67aa3c6cb808c093e7d83cd59799f1ee7d0` and
|
|
140
140
|
read the pinned guide before implementing protocol details. If this skill is installed
|
|
141
141
|
without its sibling, the scaffolder is absent: create the bundle by hand from the pinned
|
|
142
142
|
contract's `docs/guides/connecting-compatible-agents.md` and mark the structural check
|
|
@@ -22,7 +22,14 @@ need from Fabric. In Claude Code they live in the plugin's `hooks/hooks.json` an
|
|
|
22
22
|
| SessionStart (`startup`, `clear`; the plugin's matcher, and the script ignores `compact` and `resume` for every host) | Claude Code has an MCP server named `fabric` (local, project or user scope) | Fabric running: adds the preamble: `fabric_whoami` first; `com.status` and `com.list`, `com.read_ack` only what was read; `fabric_work_list`, then `fabric_work_claim`; `fabric_work_release` at the end; ask another Project only through `com.submit`. Fabric down, in a project that uses Fabric (below): one line, skip `fabric_whoami` and the board, start Fabric through the lifecycle broker only if the task needs it. Fabric down anywhere else, or not registered: nothing. |
|
|
23
23
|
| Stop (each turn) | as for SessionStart, and the running Fabric's `hub.json` lists `"session-hooks/1"` in `features` | measures the turn's facts (HEAD, files changed, lines added and removed: counts and ids only, git sharing 1.5 s), spools them in one entry and starts a detached worker that sends `fabric_session_observe {event: "turn", head, filesChanged, linesAdded, linesRemoved, …}` as stored, then reads `com.status` and keeps the unread count in the session's spool (`board.json`) |
|
|
24
24
|
| UserPromptSubmit | the session's spool holds a count | adds ONE line, `N unread on the project board: com.list`, only when the count rose since the last line; a fall or the same count says nothing. It reads two small files and never calls Fabric. |
|
|
25
|
-
| SessionEnd | as for Stop | spools the end; the worker sends `fabric_work_release {claims: "session", outcome: "let-go", …}`, then `fabric_session_observe {event: "end", reason}`, and removes the session's spool |
|
|
25
|
+
| SessionEnd | as for Stop | spools the end; the worker sends `fabric_work_release {claims: "session", outcome: "let-go", …}` (with `observedAt`, the time the hook fired, where the tool's input schema names it: Fabric 0.3.9 then refuses an end from before the session enrolled), then `fabric_session_observe {event: "end", reason}`, and removes the session's spool. Reason `clear` ends nothing: `/clear` keeps the agent process and its fabric-mcp, so no claim is released and no end observed; turns already spooled still go out (since 0.42.0) |
|
|
26
|
+
|
|
27
|
+
**A resumed session and a session Fabric does not hold** (since 0.42.0, board thread `02bf19c5`). `claude --resume`
|
|
28
|
+
keeps the session id, so an end that was kept for a retry (its release got no answer) would be delivered to the resumed
|
|
29
|
+
process and release its live claims: the worker drops, with a log line, every end followed by a later turn of the same
|
|
30
|
+
id, and keeps the retry only while the end is the newest entry. When `fabric-mcp --rejoin-only` exits 3 (Fabric 0.3.9:
|
|
31
|
+
no session holds the id), the worker drops the spool, writes a `no-session` mark in the session's folder and logs it
|
|
32
|
+
once; for 15 minutes the hooks spool nothing for that id (an end removes the folder), then one rejoin tries again.
|
|
26
33
|
|
|
27
34
|
**A project that uses Fabric** (`project_uses_fabric`), cheapest sign first: `fabric` registered at local or project
|
|
28
35
|
scope for the folder (user scope is every folder's, so it says nothing about this one); a `fabric-agent.json`,
|
|
@@ -134,8 +141,8 @@ launched-session check exact.
|
|
|
134
141
|
| # | Need | Shape |
|
|
135
142
|
|---|---|---|
|
|
136
143
|
| D1 | `fabric-mcp` enrolls with the runtime session id | for `--runner claude-code`, `runtimeSessionId` = env `CLAUDE_CODE_SESSION_ID` in `fabric.session.enroll {cwd, runtimeSessionId}` (Claude Code 2.1.296 gives MCP stdio servers and Bash commands that variable, equal to the hooks' `session_id`) |
|
|
137
|
-
| D2 | rejoin only | `fabric-mcp --runner claude-code --rejoin-only --runtime-session-id <id>` attaches to that runtime session's live enrolled session; never asks, never mints; otherwise only `fabric_whoami`, as not enrolled |
|
|
144
|
+
| D2 | rejoin only | `fabric-mcp --runner claude-code --rejoin-only --runtime-session-id <id>` attaches to that runtime session's live enrolled session; never asks, never mints; otherwise only `fabric_whoami`, as not enrolled; Fabric 0.3.9 exits 3 at once when no session holds the id |
|
|
138
145
|
| D3 | the flag | `hub.json` `"features": ["session-hooks/1"]` once D1, D2, D4 and D5 ship |
|
|
139
146
|
| D4 | `fabric_session_observe` | `{event: "turn" or "end", runtime: "claude-code", runtimeSessionId, observedAt, head, filesChanged, linesAdded, linesRemoved, reason (end only), idempotencyKey}` → `session.turn.observed@1`, `session.ended@1` |
|
|
140
|
-
| D5 | release a whole session | `fabric_work_release {claims: "session", outcome: "let-go", reason, idempotencyKey}` |
|
|
147
|
+
| D5 | release a whole session | `fabric_work_release {claims: "session", outcome: "let-go", reason, idempotencyKey}`; `observedAt` too where its input schema names it (Fabric 0.3.9: `stale-end` for an end observed before the session enrolled) |
|
|
141
148
|
| D6 | a launched-session marker | `FABRIC_LAUNCHED_SESSION=1` in the environment of every session Fabric launches, whatever its adapter; until then, the inference above |
|
|
@@ -67,6 +67,9 @@ from fabric_session_env import ( # noqa: F401
|
|
|
67
67
|
lock_held,
|
|
68
68
|
spawn_worker,
|
|
69
69
|
_remove_tree,
|
|
70
|
+
NO_SESSION_MARK,
|
|
71
|
+
NO_SESSION_HOLD_S,
|
|
72
|
+
no_session_held,
|
|
70
73
|
)
|
|
71
74
|
from fabric_session_mcp import ( # noqa: F401
|
|
72
75
|
RUNNER,
|
|
@@ -87,6 +90,8 @@ from fabric_session_mcp import ( # noqa: F401
|
|
|
87
90
|
board_unread,
|
|
88
91
|
deliver,
|
|
89
92
|
_wait_for_session_tools,
|
|
93
|
+
NO_SESSION_EXIT,
|
|
94
|
+
NoSessionError,
|
|
90
95
|
)
|
|
91
96
|
from fabric_session_mail import ( # noqa: F401
|
|
92
97
|
WATCH_MIN_INTERVAL_S,
|
package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_cli.py
CHANGED
|
@@ -29,6 +29,7 @@ from fabric_session_env import ( # noqa: E402 - the kit (FAA-65)
|
|
|
29
29
|
locate_hub,
|
|
30
30
|
lock_held,
|
|
31
31
|
log,
|
|
32
|
+
no_session_held,
|
|
32
33
|
project_uses_fabric,
|
|
33
34
|
prune_stale_sessions,
|
|
34
35
|
read_small,
|
|
@@ -169,6 +170,19 @@ def hook_spool(payload: Dict[str, Any], event: str, env: Optional[Dict[str, str]
|
|
|
169
170
|
if event == "end":
|
|
170
171
|
_remove_tree(directory)
|
|
171
172
|
return "skipped: launched by Fabric"
|
|
173
|
+
if event == "end" and payload.get("reason") == "clear":
|
|
174
|
+
# /clear keeps the agent process and its fabric-mcp; Fabric 0.3.9 renames the session to the new id (board
|
|
175
|
+
# thread 02bf19c5, ask 2). No claim is released and no end observed; turns already spooled still go out.
|
|
176
|
+
# Spawned even while a worker runs: that one may have read the spool before the last turn landed, and no
|
|
177
|
+
# later hook comes for this id. The new worker waits for the lock and finds an empty spool at worst.
|
|
178
|
+
if any(directory.glob("*-turn.json")):
|
|
179
|
+
spawn(directory)
|
|
180
|
+
return "skipped: /clear keeps the Fabric session"
|
|
181
|
+
if no_session_held(directory):
|
|
182
|
+
# A rejoin found no Fabric session for this id (02bf19c5, ask 4): recorded once, never retried every turn.
|
|
183
|
+
if event == "end":
|
|
184
|
+
_remove_tree(directory)
|
|
185
|
+
return "skipped: Fabric holds no session for it"
|
|
172
186
|
# The ancestor check costs a process-table read or two: only once per session, when its folder is first made. A
|
|
173
187
|
# positive answer is kept in the folder; an unknown one (a `ps` that failed) spools nothing, so no worker can
|
|
174
188
|
# release a launched session's claims, and is asked again at the next hook.
|
package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py
CHANGED
|
@@ -57,7 +57,7 @@ SESSION_ID = re.compile(r"[A-Za-z0-9._:-]{1,128}")
|
|
|
57
57
|
LOOPBACK_ORIGIN = re.compile(r"http://127\.0\.0\.1:(\d{1,5})")
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
VERSION = "0.
|
|
60
|
+
VERSION = "0.43.0"
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
HOSTS = {"claude": "Claude Code", "codex": "Codex", "kimi": "Kimi Code",
|
|
@@ -435,6 +435,23 @@ REJOIN_MIN_INTERVAL_S = 60.0
|
|
|
435
435
|
LAUNCHED_MARK = "launched"
|
|
436
436
|
|
|
437
437
|
|
|
438
|
+
#: The file in a session's folder that says Fabric held no session for its id: fabric-mcp --rejoin-only exited 3
|
|
439
|
+
#: (Fabric 0.3.9, TR-11). For NO_SESSION_HOLD_S the hooks spool nothing for that id; after it, one rejoin tries again,
|
|
440
|
+
#: so a Fabric that restarted and enrolled the id again is found (board thread 02bf19c5, ask 4).
|
|
441
|
+
NO_SESSION_MARK = "no-session"
|
|
442
|
+
NO_SESSION_HOLD_S = 15 * 60.0
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def no_session_held(directory: Path, now: Optional[float] = None) -> bool:
|
|
446
|
+
"""Whether a rejoin found no Fabric session for this id within NO_SESSION_HOLD_S."""
|
|
447
|
+
try:
|
|
448
|
+
mark = (directory / NO_SESSION_MARK).stat().st_mtime
|
|
449
|
+
except OSError:
|
|
450
|
+
return False
|
|
451
|
+
age = (time.time() if now is None else now) - mark
|
|
452
|
+
return 0 <= age < NO_SESSION_HOLD_S
|
|
453
|
+
|
|
454
|
+
|
|
438
455
|
def rejoined_recently(directory: Path, now: Optional[float] = None) -> bool:
|
|
439
456
|
"""Whether this session's last rejoin succeeded within REJOIN_MIN_INTERVAL_S (the worker marks it)."""
|
|
440
457
|
return rejoin_wait(directory, now) > 0
|
package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mail.py
CHANGED
|
@@ -25,6 +25,7 @@ from fabric_session_env import ( # noqa: E402 - the kit (FAA-65)
|
|
|
25
25
|
)
|
|
26
26
|
from fabric_session_mcp import ( # noqa: E402 - the kit (FAA-65)
|
|
27
27
|
McpStdio,
|
|
28
|
+
NoSessionError,
|
|
28
29
|
_wait_for_session_tools,
|
|
29
30
|
board_unread,
|
|
30
31
|
)
|
|
@@ -74,6 +75,8 @@ def poll_unread(session_id: str, cwd: Path, env: Optional[Dict[str, str]] = None
|
|
|
74
75
|
return "unavailable", "this Fabric serves no %s" % BOARD_STATUS_TOOL
|
|
75
76
|
unread, said = board_unread(client.request("tools/call", {"name": BOARD_STATUS_TOOL, "arguments": {}}))
|
|
76
77
|
return ("ok", unread) if unread is not None else ("unavailable", "the project board cannot be read (%s)" % said)
|
|
78
|
+
except NoSessionError:
|
|
79
|
+
return "down", "Fabric holds no session for this id"
|
|
77
80
|
except TimeoutError:
|
|
78
81
|
return "down", "fabric-mcp did not join this session in time"
|
|
79
82
|
except Exception as exc: # noqa: BLE001 — a poll never raises
|
package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_mcp.py
CHANGED
|
@@ -21,6 +21,7 @@ from fabric_session_env import ( # noqa: E402 - the kit (FAA-65)
|
|
|
21
21
|
GIT_TIMEOUT_S,
|
|
22
22
|
HOOK_FEATURE,
|
|
23
23
|
LOCK_STALE_S,
|
|
24
|
+
NO_SESSION_MARK,
|
|
24
25
|
SESSION_ID,
|
|
25
26
|
VERSION,
|
|
26
27
|
WORKER_DEADLINE_S,
|
|
@@ -127,6 +128,15 @@ class JsonRpcError(RuntimeError):
|
|
|
127
128
|
return "error:%s" % ("unnamed" if self.code is None else self.code)
|
|
128
129
|
|
|
129
130
|
|
|
131
|
+
#: fabric-mcp --rejoin-only's exit status when no Fabric session holds the runtime id (Fabric 0.3.9, TR-11).
|
|
132
|
+
NO_SESSION_EXIT = 3
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class NoSessionError(TimeoutError):
|
|
136
|
+
"""fabric-mcp --rejoin-only ended with NO_SESSION_EXIT: Fabric holds no session for this id. A TimeoutError, so a
|
|
137
|
+
caller that knows only "no answer" (watch-mail) keeps treating it as one."""
|
|
138
|
+
|
|
139
|
+
|
|
130
140
|
class McpStdio:
|
|
131
141
|
"""A minimal MCP client over stdio (newline-delimited JSON-RPC) with a hard deadline."""
|
|
132
142
|
|
|
@@ -150,6 +160,7 @@ class McpStdio:
|
|
|
150
160
|
self.cond = threading.Condition()
|
|
151
161
|
self.next_id = 0
|
|
152
162
|
self.tools_changed = False
|
|
163
|
+
self.tools: List[Dict[str, Any]] = [] # the last tools/list answer, for the tools' input schemas
|
|
153
164
|
self.reader = threading.Thread(target=self._read, daemon=True)
|
|
154
165
|
self.reader.start()
|
|
155
166
|
|
|
@@ -169,10 +180,23 @@ class McpStdio:
|
|
|
169
180
|
with self.cond:
|
|
170
181
|
self.cond.notify_all()
|
|
171
182
|
|
|
183
|
+
def _ended(self) -> None:
|
|
184
|
+
"""The server is gone: raise what its exit status says."""
|
|
185
|
+
if self.proc.returncode == NO_SESSION_EXIT:
|
|
186
|
+
raise NoSessionError("fabric-mcp found no session for this id")
|
|
187
|
+
raise TimeoutError("fabric-mcp ended")
|
|
188
|
+
|
|
172
189
|
def _send(self, message: Dict[str, Any]) -> None:
|
|
173
190
|
assert self.proc.stdin is not None
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
try:
|
|
192
|
+
self.proc.stdin.write((json.dumps(message) + "\n").encode("utf-8"))
|
|
193
|
+
self.proc.stdin.flush()
|
|
194
|
+
except OSError: # a server that exited closed its stdin: say why it exited, never a broken pipe
|
|
195
|
+
try:
|
|
196
|
+
self.proc.wait(timeout=max(0.0, min(1.0, self.deadline - time.monotonic())))
|
|
197
|
+
except subprocess.TimeoutExpired:
|
|
198
|
+
pass
|
|
199
|
+
self._ended()
|
|
176
200
|
|
|
177
201
|
def notify(self, method: str, params: Optional[Dict[str, Any]] = None) -> None:
|
|
178
202
|
self._send({"jsonrpc": "2.0", "method": method, **({"params": params} if params else {})})
|
|
@@ -191,7 +215,9 @@ class McpStdio:
|
|
|
191
215
|
raise JsonRpcError(error.get("code") if isinstance(error, dict) else None)
|
|
192
216
|
return message.get("result") or {}
|
|
193
217
|
left = self.deadline - time.monotonic()
|
|
194
|
-
if
|
|
218
|
+
if self.proc.poll() is not None:
|
|
219
|
+
self._ended()
|
|
220
|
+
if left <= 0:
|
|
195
221
|
raise TimeoutError("no answer to %s" % method)
|
|
196
222
|
self.cond.wait(min(left, 0.25))
|
|
197
223
|
|
|
@@ -402,7 +428,7 @@ def deliver(directory: Path, env: Optional[Dict[str, str]] = None, deadline_s: f
|
|
|
402
428
|
note("session=%s event=%s tool=%s answer=%s" % (session_id[:8], event, tool, answer))
|
|
403
429
|
|
|
404
430
|
try:
|
|
405
|
-
entries = sorted(directory.glob("*-*.json"))
|
|
431
|
+
entries = _drop_stale_ends(sorted(directory.glob("*-*.json")), note, session_id)
|
|
406
432
|
if not entries:
|
|
407
433
|
return said
|
|
408
434
|
cwd = _entry_cwd(entries)
|
|
@@ -435,10 +461,14 @@ def deliver(directory: Path, env: Optional[Dict[str, str]] = None, deadline_s: f
|
|
|
435
461
|
reason = entry.get("reason") if isinstance(entry.get("reason"), str) else "other"
|
|
436
462
|
if event == "end":
|
|
437
463
|
if RELEASE_TOOL in names:
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
464
|
+
release = {"claims": "session", "outcome": "let-go",
|
|
465
|
+
"reason": "the Claude Code session ended (%s)" % reason,
|
|
466
|
+
"idempotencyKey": key + ":release"}
|
|
467
|
+
# Fabric 0.3.9 refuses an end observed before the session enrolled (`stale-end`, board thread
|
|
468
|
+
# 02bf19c5): say when it was observed, where the tool takes the field.
|
|
469
|
+
if isinstance(entry.get("observedAt"), str) and "observedAt" in _input_fields(client, RELEASE_TOOL):
|
|
470
|
+
release["observedAt"] = entry["observedAt"]
|
|
471
|
+
call(event, RELEASE_TOOL, release)
|
|
442
472
|
else:
|
|
443
473
|
note("session=%s event=end outcome=degraded reason=%r" % (session_id[:8], "no %s" % RELEASE_TOOL))
|
|
444
474
|
if OBSERVE_TOOL in names:
|
|
@@ -453,7 +483,7 @@ def deliver(directory: Path, env: Optional[Dict[str, str]] = None, deadline_s: f
|
|
|
453
483
|
path.unlink()
|
|
454
484
|
if event == "end":
|
|
455
485
|
ended = True # only now: a call that timed out above left this entry for the next worker
|
|
456
|
-
entries = sorted(directory.glob("*-*.json")) #
|
|
486
|
+
entries = _drop_stale_ends(sorted(directory.glob("*-*.json")), note, session_id) # spooled meanwhile
|
|
457
487
|
if not ended and BOARD_STATUS_TOOL in names:
|
|
458
488
|
# The board's unread count for the prompt hook (FAA-12a). A count, never a message.
|
|
459
489
|
try:
|
|
@@ -463,6 +493,19 @@ def deliver(directory: Path, env: Optional[Dict[str, str]] = None, deadline_s: f
|
|
|
463
493
|
_write_private(directory / "board.json", json.dumps({
|
|
464
494
|
"unread": unread, "observedAt": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())}))
|
|
465
495
|
note("session=%s event=board tool=%s %s" % (session_id[:8], BOARD_STATUS_TOOL, said_board))
|
|
496
|
+
except NoSessionError:
|
|
497
|
+
# Recorded once (02bf19c5, ask 4): nothing in the spool can reach a session Fabric does not hold.
|
|
498
|
+
note("session=%s outcome=no-session reason=%r" % (session_id[:8], "Fabric holds no session for this id"))
|
|
499
|
+
for path in directory.glob("*-*.json"):
|
|
500
|
+
ended = ended or path.name.endswith("-end.json") # the session's last hook: its folder goes now
|
|
501
|
+
try:
|
|
502
|
+
path.unlink()
|
|
503
|
+
except OSError:
|
|
504
|
+
pass
|
|
505
|
+
try:
|
|
506
|
+
_write_private(directory / NO_SESSION_MARK, "")
|
|
507
|
+
except OSError as exc: # the worker never raises: without the mark, the next turn tries once more
|
|
508
|
+
note("session=%s outcome=no-session reason=%r" % (session_id[:8], "the mark was not written (%s)" % type(exc).__name__))
|
|
466
509
|
except TimeoutError as exc:
|
|
467
510
|
note("session=%s outcome=unknown reason=%r" % (session_id[:8], str(exc)))
|
|
468
511
|
except Exception as exc: # noqa: BLE001 — the worker never raises
|
|
@@ -479,10 +522,39 @@ def deliver(directory: Path, env: Optional[Dict[str, str]] = None, deadline_s: f
|
|
|
479
522
|
return said
|
|
480
523
|
|
|
481
524
|
|
|
525
|
+
def _drop_stale_ends(entries: List[Path], note: Callable[[str], None], session_id: str) -> List[Path]:
|
|
526
|
+
"""The entries left once every end followed by a later turn of the same id is dropped (FAA-83; board thread
|
|
527
|
+
02bf19c5, ask 3): `claude --resume` keeps the id, so such an end belongs to an earlier process of the session, and
|
|
528
|
+
delivering it would release the live session's claims. An end that is the newest entry keeps its retry. Entries
|
|
529
|
+
are named by `time_ns`, so the sorted order is the spooling order."""
|
|
530
|
+
kept: List[Path] = []
|
|
531
|
+
for index, path in enumerate(entries):
|
|
532
|
+
if path.name.endswith("-end.json") and any(p.name.endswith("-turn.json") for p in entries[index + 1:]):
|
|
533
|
+
note("session=%s event=end outcome=dropped reason=%r" % (session_id[:8], "a later turn of the same session"))
|
|
534
|
+
try:
|
|
535
|
+
path.unlink()
|
|
536
|
+
except OSError:
|
|
537
|
+
pass
|
|
538
|
+
continue
|
|
539
|
+
kept.append(path)
|
|
540
|
+
return kept
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def _input_fields(client: McpStdio, tool: str) -> List[str]:
|
|
544
|
+
"""The property names a listed tool's input schema declares; [] when it declares none."""
|
|
545
|
+
for listed in client.tools:
|
|
546
|
+
if listed.get("name") == tool:
|
|
547
|
+
schema = listed.get("inputSchema")
|
|
548
|
+
props = schema.get("properties") if isinstance(schema, dict) else None
|
|
549
|
+
return [k for k in props if isinstance(k, str)] if isinstance(props, dict) else []
|
|
550
|
+
return []
|
|
551
|
+
|
|
552
|
+
|
|
482
553
|
def _wait_for_session_tools(client: McpStdio, deadline: float) -> List[str]:
|
|
483
554
|
"""fabric-mcp lists only fabric_whoami until it holds a session; then it says its tools changed."""
|
|
484
555
|
while True:
|
|
485
556
|
tools = client.request("tools/list", {}).get("tools") or []
|
|
557
|
+
client.tools = [t for t in tools if isinstance(t, dict)]
|
|
486
558
|
names = [t.get("name") for t in tools if isinstance(t, dict) and isinstance(t.get("name"), str)]
|
|
487
559
|
if [n for n in names if n != WAITING_TOOL]:
|
|
488
560
|
return names
|