@passioncode-ai/passioncode 0.1.20 → 0.1.22

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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.22 - 2026-10-03
4
+
5
+ ### Changed
6
+
7
+ - **Observatory Log is pinned at `v0.13.0`** (plugin 0.14.0; it was `v0.10.0`, plugin 0.13.0),
8
+ the Project Observatory 0.13.0 hook and skills. The hook and the skills hand over the installed
9
+ engine's commands (`project-observatory full findings`, `full doctor`) instead of source-tree
10
+ paths, and the skills' own check runs under the interpreter `full agent install` records. In
11
+ `handling-secrets`, a vault `PROJECT` is the project's folder name and its registry id resolves to
12
+ the same folder. `use_secret.py run` takes `--env`, and `vault.py remove` deletes a slot or only
13
+ its retired archives.
14
+
15
+ ## 0.1.21 - 2026-10-03
16
+
17
+ ### Changed
18
+
19
+ - **Fabric Agent Adapter is pinned at `v0.6.1`:** `check_service.py` no longer fails an online
20
+ service hosted behind a platform router. Heroku, Fly, Render and CDNs answer a foreign `Host`
21
+ themselves (`404`/`421`), and that now counts as the refusal it is, unless the body is the
22
+ well-known document.
23
+
3
24
  ## 0.1.20 - 2026-10-02
4
25
 
5
26
  ### Changed
package/family.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "name": "fabric-agent-adapter",
9
9
  "displayName": "Fabric Agent Adapter",
10
10
  "repo": "passioncode-ai/fabric-agent-adapter",
11
- "ref": "v0.6.0",
11
+ "ref": "v0.6.1",
12
12
  "kind": "plugin",
13
13
  "path": "plugins/fabric-agent-adapter",
14
14
  "legacyPluginIds": [
@@ -22,7 +22,7 @@
22
22
  "name": "observatory-log",
23
23
  "displayName": "Observatory Log",
24
24
  "repo": "passioncode-ai/project-observatory-dashboard",
25
- "ref": "v0.10.0",
25
+ "ref": "v0.13.0",
26
26
  "kind": "plugin",
27
27
  "path": "observatory/engine/skill/plugins/observatory-log",
28
28
  "legacyPluginIds": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@passioncode-ai/passioncode",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "The PassionCode.ai agent skill set \u2014 Fabric Agent Adapter, Observatory Log and the organisation's working rules \u2014 for Claude Code and every other agent on the machine, updated as one set.",
5
5
  "bin": {
6
6
  "passioncode": "bin/passioncode.js"
@@ -11,7 +11,7 @@
11
11
  "name": "fabric-agent-adapter",
12
12
  "displayName": "Fabric Agent Adapter",
13
13
  "source": "./plugins/fabric-agent-adapter",
14
- "version": "0.6.0",
14
+ "version": "0.6.1",
15
15
  "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.",
16
16
  "author": {
17
17
  "name": "PassionCode.ai",
@@ -23,7 +23,7 @@
23
23
  "name": "observatory-log",
24
24
  "displayName": "Observatory Log",
25
25
  "source": "./plugins/observatory-log",
26
- "version": "0.13.0",
26
+ "version": "0.14.0",
27
27
  "description": "Records what changed in a watched project at the end of every turn, and asks for the one thing a diff cannot contain: why.",
28
28
  "author": {
29
29
  "name": "PassionCode.ai",
@@ -35,7 +35,7 @@
35
35
  "name": "passioncode",
36
36
  "displayName": "PassionCode.ai",
37
37
  "source": "./plugins/passioncode",
38
- "version": "0.1.20",
38
+ "version": "0.1.22",
39
39
  "description": "The organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
40
40
  "author": {
41
41
  "name": "PassionCode.ai",
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "family": "passioncode",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "release": true,
5
5
  "members": [
6
6
  {
7
7
  "name": "fabric-agent-adapter",
8
8
  "displayName": "Fabric Agent Adapter",
9
9
  "repo": "passioncode-ai/fabric-agent-adapter",
10
- "ref": "v0.6.0",
11
- "commit": "447b55819b83d25f168afa7abd99cafa0ab29812",
12
- "version": "0.6.0",
10
+ "ref": "v0.6.1",
11
+ "commit": "d3a4c67262e242b0a4422ecdcf99a7d892db6caa",
12
+ "version": "0.6.1",
13
13
  "via": "clone of https://***@github.com/passioncode-ai/fabric-agent-adapter.git",
14
14
  "skills": [
15
15
  "adapting-projects-to-fabric",
@@ -22,7 +22,7 @@
22
22
  "legacyMarketplaces": [
23
23
  "fabric-agent-adapter"
24
24
  ],
25
- "contentHash": "sha256:f714e1620093378f3c790287270608ad8b6084109e813eead03dea9c159e964e",
25
+ "contentHash": "sha256:654511f4332892aa9a709e1946566d017179edc294e136fbe5c6466c5c32b5c8",
26
26
  "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.",
27
27
  "author": {
28
28
  "name": "PassionCode.ai",
@@ -34,9 +34,9 @@
34
34
  "name": "observatory-log",
35
35
  "displayName": "Observatory Log",
36
36
  "repo": "passioncode-ai/project-observatory-dashboard",
37
- "ref": "v0.10.0",
38
- "commit": "e1e0110f6618b9541f3e204a548c283005cb6fa9",
39
- "version": "0.13.0",
37
+ "ref": "v0.13.0",
38
+ "commit": "c7a89125edcd5ee1a8141feb55d4aca2c828e834",
39
+ "version": "0.14.0",
40
40
  "via": "clone of https://***@github.com/passioncode-ai/project-observatory-dashboard.git",
41
41
  "skills": [
42
42
  "explaining-changes",
@@ -49,7 +49,7 @@
49
49
  "legacyMarketplaces": [
50
50
  "observatory-log"
51
51
  ],
52
- "contentHash": "sha256:1514d04e995ecd71df0e0518787d76c9320b02f8174824d08c958846b860fd42",
52
+ "contentHash": "sha256:3e1218586122889649881d94fdf892f6a51782dc748c26127a9969376ecdf1eb",
53
53
  "description": "Records what changed in a watched project at the end of every turn, and asks for the one thing a diff cannot contain: why.",
54
54
  "author": {
55
55
  "name": "PassionCode.ai",
@@ -61,16 +61,16 @@
61
61
  "name": "passioncode",
62
62
  "displayName": "PassionCode.ai",
63
63
  "repo": "passioncode-ai/passioncode",
64
- "ref": "v0.1.20",
64
+ "ref": "v0.1.22",
65
65
  "commit": null,
66
- "version": "0.1.20",
66
+ "version": "0.1.22",
67
67
  "via": "this repository",
68
68
  "skills": [
69
69
  "working-in-passioncode"
70
70
  ],
71
71
  "legacyPluginIds": [],
72
72
  "legacyMarketplaces": [],
73
- "contentHash": "sha256:b230828150120df33b6c48eccf6a6d4e20e35f0dff8089df4d9554c29957016a",
73
+ "contentHash": "sha256:41d5e5549a6fb2ace8f68766c3fad8fc2c72197b2896a8ae934b1a2029eba0ec",
74
74
  "description": "The organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
75
75
  "author": {
76
76
  "name": "PassionCode.ai",
@@ -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.",
6
- "version": "0.6.0",
6
+ "version": "0.6.1",
7
7
  "author": {
8
8
  "name": "PassionCode.ai",
9
9
  "url": "https://passioncode.ai/"
@@ -5,7 +5,7 @@ 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.6.0"
8
+ version: "0.6.1"
9
9
  contract-version: "0.1.0"
10
10
  contract-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
11
11
  ---
@@ -15,7 +15,7 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
15
15
  compatibility: Python 3.9+ or Node.js 20+ for the kits; the probe needs Python 3.9+. launchd steps are macOS-only (Linux services use lifecycle manager none until a systemd adapter exists). Dashboard handoff optionally uses Fabric Dashboards MCP link/host_status/open; without it, report unresolved host capability. The contract checkout is optional.
16
16
  metadata:
17
17
  author: PassionCode.ai
18
- version: "0.6.0"
18
+ version: "0.6.1"
19
19
  contract-version: "0.1.0"
20
20
  extension: "fabric-service/0.1"
21
21
  extension-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
@@ -44,6 +44,14 @@ same objects — well-known document, events feed, login code — at the same pa
44
44
  - **Behind a router**: check the platform-set forwarded scheme; `Host` is preserved by common
45
45
  platforms and must equal the origin's host.
46
46
 
47
+ ## Checking it
48
+
49
+ `check_service.py <id>` probes a remote placement over verified TLS. Behind a platform router
50
+ (Heroku, Fly, Render, a CDN) a request that names a foreign `Host` never reaches the process: the
51
+ router answers it, usually `404` or `421`. The probe counts that as the refusal it is, as long as
52
+ the body is not the well-known document. The Origin and cross-site checks name the right `Host`,
53
+ reach the service, and still need its own `403`.
54
+
47
55
  ## What a host does and will not do
48
56
 
49
57
  | Situation | Host |
@@ -79,6 +79,23 @@ def priority_problems(plist: dict) -> list:
79
79
  return out
80
80
 
81
81
 
82
+ # A platform router (Heroku, Fly, Render, a CDN) routes by Host, so a request naming a foreign
83
+ # Host never reaches an online service: the router itself answers, typically 404 or 421. That is
84
+ # still a refusal — the service disclosed nothing — so for a remote placement the host check
85
+ # accepts it, as long as the body is not the well-known document. Every other guard request names
86
+ # the right Host, reaches the service, and must be the service's own 403.
87
+ PLATFORM_HOST_REFUSALS = (400, 404, 421)
88
+
89
+
90
+ def guard_verdict(rule: str, remote: bool, status: int, body: bytes) -> Tuple[str, str]:
91
+ if status == 403:
92
+ return "PASS", "HTTP 403"
93
+ disclosed = b"fabric-service/" in (body or b"")
94
+ if rule == "network.host-check" and remote and status in PLATFORM_HOST_REFUSALS and not disclosed:
95
+ return "PASS", "HTTP %d from the platform router: a foreign Host never reaches the service" % status
96
+ return "FAIL", "HTTP %d%s" % (status, ", and the body is the well-known document" if disclosed else "")
97
+
98
+
82
99
  class _PinnedHTTPS(http.client.HTTPSConnection):
83
100
  """HTTPS to the origin's name (SNI, certificate, Host) over a socket dialled elsewhere."""
84
101
 
@@ -243,8 +260,9 @@ class Probe:
243
260
  sent.update(self.auth_headers())
244
261
  if "Origin" in sent:
245
262
  sent["Origin"] = "https://evil.example"
246
- status, _, _ = self.request("GET", "/.well-known/fabric-service", sent)
247
- self.add(rule, "PASS" if status == 403 else "FAIL", "HTTP %d" % status)
263
+ status, _, body = self.request("GET", "/.well-known/fabric-service", sent)
264
+ verdict, evidence = guard_verdict(rule, self.remote, status, body)
265
+ self.add(rule, verdict, evidence)
248
266
  except (OSError, ssl.SSLError) as exc:
249
267
  self.add(rule, "NOT_RUN", str(exc))
250
268
  if self.remote:
@@ -5,7 +5,7 @@ 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.6.0"
8
+ version: "0.6.1"
9
9
  contract-version: "0.1.0"
10
10
  contract-commit: "2ce392291c6668598d12cd38327e24696b5ca15c"
11
11
  ---
@@ -3,7 +3,7 @@
3
3
  "name": "observatory-log",
4
4
  "displayName": "Observatory Log",
5
5
  "description": "Records what changed in a watched project at the end of every turn, and asks for the one thing a diff cannot contain: why.",
6
- "version": "0.13.0",
6
+ "version": "0.14.0",
7
7
  "license": "AGPL-3.0-only OR LicenseRef-PassionCode-Commercial",
8
8
  "author": {
9
9
  "name": "PassionCode.ai",
@@ -40,7 +40,7 @@ def main() -> int:
40
40
  "Observatory could NOT record this turn: " + reason +
41
41
  "\n\nThe facts of this turn are not in the ledger. "
42
42
  "`store/raw/record-turn.json` holds the same reason, and "
43
- "`./observatory.py findings` raises it.",
43
+ "`project-observatory full findings` raises it.",
44
44
  "suppressOutput": True}))
45
45
  return 0
46
46
  if r.get("hasWhy"):
@@ -15,7 +15,7 @@ description: >-
15
15
  decision with different evidence.
16
16
  license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
17
17
  metadata:
18
- version: "0.13.0"
18
+ version: "0.14.0"
19
19
  compatibility: >-
20
20
  Requires an initialized full Project Observatory installation to persist
21
21
  records. Uses its MCP server when available in the current host; the bundled
@@ -9,7 +9,7 @@ description: >-
9
9
  provider permissions or choosing a project's authentication architecture.
10
10
  license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
11
11
  metadata:
12
- version: "0.13.0"
12
+ version: "0.14.0"
13
13
  compatibility: >-
14
14
  Requires an initialized full Project Observatory installation, Python 3.11+
15
15
  and local shell access on macOS or Linux. Provider operations additionally
@@ -27,9 +27,10 @@ names. Never ask the user to paste a credential into the conversation.
27
27
  `OBSERVATORY_ROOT`, or obtain its path with `project-observatory full-path`.
28
28
  Do not guess a checkout location or inspect another account's files.
29
29
  2. Select the user's initialized `OBSERVATORY_HOME`. Run
30
- `python3 "$OBSERVATORY_ROOT/observatory.py" doctor`. A missing workspace
30
+ `project-observatory full doctor`. A missing workspace
31
31
  needs the documented onboarding before secret operations.
32
- 3. Run `python3 "$OBSERVATORY_ROOT/tools/skill_check.py" handling-secrets 0.13.0`.
32
+ 3. Run `"$OBSERVATORY_PYTHON" "$OBSERVATORY_ROOT/tools/skill_check.py" handling-secrets 0.14.0`
33
+ (`full agent install` records that interpreter; the stock macOS `python3` is too old).
33
34
  If stale, read the installed skill once and follow its compatible commands.
34
35
  Do not turn an unavailable version check into a retry loop.
35
36
  4. Inspect names using `tools/use_secret.py names PROJECT` or `tools/vault.py
@@ -37,8 +38,11 @@ names. Never ask the user to paste a credential into the conversation.
37
38
  Never read a value file to discover whether it exists.
38
39
 
39
40
  All commands below are Python scripts under `OBSERVATORY_ROOT/tools`. `PROJECT`,
40
- `ENV` and `NAME` are placeholders for existing user-selected names. `ENV` is
41
- `local`, `stage` or `prod`; choose production only when the task calls for it.
41
+ `ENV` and `NAME` are placeholders for existing user-selected names. `PROJECT` is
42
+ the project's folder name; its registry id (`project:<slug>` or the bare slug) is
43
+ accepted and normalised to that folder, and a name two projects claim is refused.
44
+ `ENV` is `local`, `stage` or `prod`; choose production only when the task calls
45
+ for it. A name or note shaped like a credential is refused, never stored.
42
46
 
43
47
  ## Use the named door
44
48
 
@@ -46,13 +50,14 @@ All commands below are Python scripts under `OBSERVATORY_ROOT/tools`. `PROJECT`,
46
50
  |---|---|
47
51
  | Store a credential supplied locally | `vault.py put PROJECT ENV NAME`, value on stdin |
48
52
  | List slots | `vault.py list PROJECT ENV` |
49
- | Run a command using a slot | `use_secret.py run PROJECT NAME -- COMMAND ARGUMENTS` |
53
+ | Run a command using a slot | `use_secret.py run [--env ENV] PROJECT NAME -- COMMAND ARGUMENTS` (flags before PROJECT) |
50
54
  | Receive a value from another local command | `use_secret.py pipe NAME -- COMMAND ARGUMENTS` |
51
55
  | Populate a project's ignored environment file | `vault.py inject PROJECT ENV DIRECTORY` |
52
56
  | Record an exposure | `vault.py leak PROJECT ENV NAME --where "location and evidence, no value"` |
53
57
  | Replace a stored value | `vault.py rotate PROJECT ENV NAME`, replacement on stdin |
54
58
  | Close an exposure after revocation and consumer checks | `vault.py settle PROJECT ENV NAME --how "action" --revocation-evidence "receipt" --consumer-evidence "receipt"` |
55
59
  | Record an external movement | `vault.py moved PROJECT ENV NAME --at PROVIDER --how "action and evidence"`; add `--settle` with both evidence flags to also close its exposure |
60
+ | Delete a slot, or only the archives a rotation left | `vault.py remove PROJECT ENV NAME` (refused while its exposure is open unless `--force`), or `vault.py remove PROJECT ENV NAME --retired`; both are journalled |
56
61
  | Review unresolved exposures or movements | `vault.py leaks` or `vault.py movements PROJECT` |
57
62
 
58
63
  Use the installed command's `--help` for optional flags. Avoid placing a value
@@ -135,7 +140,8 @@ By default, slots live under the private workspace's `secrets/projects/`.
135
140
  An explicitly configured `sources.secret_store` or `OBSERVATORY_VAULT_DIR`
136
141
  can select a separate private store. Such external stores are excluded from
137
142
  workspace backups and need their own backup procedure. `vault.py backup`
138
- requires a configured gateway backup script; do not promise encryption,
143
+ requires a configured gateway backup script (`backup-secrets.sh` at
144
+ `sources.gateway_root` or in its `bin/`); do not promise encryption,
139
145
  keychain storage or scheduled backups when that integration is absent.
140
146
 
141
147
  ## When something is unavailable
@@ -15,7 +15,7 @@ description: >-
15
15
  the repository.
16
16
  license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
17
17
  metadata:
18
- version: "0.13.0"
18
+ version: "0.14.0"
19
19
  compatibility: >-
20
20
  Requires a full Project Observatory installation with organizations.json
21
21
  configured; the observatory MCP server or its local CLI. Creating the resource
@@ -58,7 +58,7 @@ Report each resource with `observatory_propose`:
58
58
  "targetId": "project:<slug>",
59
59
  "patch": {"resources": [{"kind": "ga4-property",
60
60
  "identifier": "properties/123456789",
61
- "account": "accounts/162941847",
61
+ "account": "accounts/123456789",
62
62
  "url": "https://analytics.google.com/…",
63
63
  "note": "web stream for example.com",
64
64
  "added_on": "2026-09-27",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "passioncode",
4
4
  "displayName": "PassionCode.ai",
5
- "version": "0.1.20",
5
+ "version": "0.1.22",
6
6
  "description": "The organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check at session start that keeps the PassionCode.ai skill set current.",
7
7
  "author": {
8
8
  "name": "PassionCode.ai",