@delorenj/pjangler 1.2.19 → 1.2.25
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/dist/index.js +2353 -518
- package/dist/mcp-server.js +2331 -494
- package/package.json +14 -3
- package/templates/commonproject/copier.yml +6 -4
- package/templates/commonproject/template/.agents/hooks/README.md +13 -26
- package/templates/commonproject/template/.agents/hooks/lib/local-config.sh +4 -14
- package/templates/commonproject/template/.agents/hooks/sync.py +5 -6
- package/templates/commonproject/template/.agents/local.example.json +2 -8
- package/templates/commonproject/template/.agents/skills.json +6 -0
- package/templates/commonproject/template/.mise/scripts/provision-bmad-skills.py +480 -0
- package/templates/commonproject/template/.mise/scripts/sync-skills.py +449 -0
- package/templates/commonproject/template/mise.toml.jinja +16 -16
- package/templates/commonproject/tests/test_provision_bmad_skills.py +203 -0
- package/templates/commonproject/tests/test_sync_skills_topology.py +120 -0
- package/templates/hermes-agent/README.md +70 -29
- package/templates/hermes-agent/copier.yml +9 -6
- package/templates/hermes-agent/docs/architecture.md +75 -51
- package/templates/hermes-agent/docs/fleet-control-plane/architecture.md +11 -6
- package/templates/hermes-agent/docs/fleet-control-plane/epics-and-stories.md +2 -2
- package/templates/hermes-agent/docs/fleet-control-plane/prd.md +2 -3
- package/templates/hermes-agent/docs/operations.md +179 -81
- package/templates/hermes-agent/docs/runbooks/runtime-checkpoint-repair.md +31 -171
- package/templates/hermes-agent/docs/sentinel/README.md +10 -10
- package/templates/hermes-agent/docs/sentinel/architecture.md +6 -8
- package/templates/hermes-agent/docs/sentinel/development.md +12 -15
- package/templates/hermes-agent/docs/sentinel.md +1 -1
- package/templates/hermes-agent/install-local.sh +41 -4
- package/templates/hermes-agent/runtime-scaffold/README.md +4 -2
- package/templates/hermes-agent/scripts/degit-runtime.sh +192 -0
- package/templates/hermes-agent/scripts/fleet-prune-debris.sh +128 -0
- package/templates/hermes-agent/scripts/fleet-sync.sh +164 -7
- package/templates/hermes-agent/scripts/hermes-runtime-templatize.py +321 -0
- package/templates/hermes-agent/scripts/migrate-profile-scoped-chat-secrets.py +136 -0
- package/templates/hermes-agent/scripts/momo-unify-agent.py +224 -0
- package/templates/hermes-agent/scripts/repair-runtime-checkpoint.sh +7 -119
- package/templates/hermes-agent/template/.gitignore.jinja +5 -2
- package/templates/hermes-agent/template/.runtime-scaffold/README.md +4 -2
- package/templates/hermes-agent/template/.scripts/00-banner.sh +1 -1
- package/templates/hermes-agent/template/.scripts/01-config.sh +3 -0
- package/templates/hermes-agent/template/.scripts/10-hermes-profile.sh +12 -1
- package/templates/hermes-agent/template/.scripts/20-runtime-repo.sh +55 -129
- package/templates/hermes-agent/template/.scripts/30-telegram.sh +276 -22
- package/templates/hermes-agent/template/.scripts/31-slack.sh +362 -0
- package/templates/hermes-agent/template/.scripts/60-bloodbank.sh +8 -66
- package/templates/hermes-agent/template/.scripts/70-systemd.sh +44 -30
- package/templates/hermes-agent/template/.scripts/80-registry.sh +93 -13
- package/templates/hermes-agent/template/.scripts/99-summary.sh +1 -4
- package/templates/hermes-agent/template/.scripts/_lib.sh +66 -1
- package/templates/hermes-agent/template/.scripts/checkpoint.sh +3 -2
- package/templates/hermes-agent/template/.scripts/config.example.toml +10 -10
- package/templates/hermes-agent/template/.scripts/heartbeat.sh +12 -1
- package/templates/hermes-agent/template/.scripts/momo-wip-lock.py +137 -0
- package/templates/hermes-agent/template/.scripts/sentinel.prompt.md.jinja +21 -0
- package/templates/hermes-agent/template/SOUL.md.jinja +36 -15
- package/templates/hermes-agent/template/hermes.jinja +6 -3
- package/templates/hermes-agent/template/role.yaml.jinja +24 -13
- package/templates/hermes-agent/tests/test_bloodbank_consumer_contract.py +429 -130
- package/templates/hermes-agent/tests/test_fleet_upgrade_contract.py +176 -0
- package/templates/hermes-agent/tests/test_launcher_chat_secret_isolation.py +85 -0
- package/templates/hermes-agent/tests/test_local_runtime_provisioning.py +130 -0
- package/templates/hermes-agent/tests/test_operator_docs_local_runtime_contract.py +132 -0
- package/templates/hermes-agent/tests/test_profile_env_detach_contract.py +14 -0
- package/templates/hermes-agent/tests/test_profile_scoped_chat_secrets.py +89 -0
- package/templates/hermes-agent/tests/test_repository_privacy_contract.py +32 -0
- package/templates/hermes-agent/tests/test_slack_provisioning.py +344 -0
- package/templates/hermes-agent/tests/test_telegram_provisioning.py +475 -0
- package/templates/commonproject/template/.mise/scripts/link-project-skills-to-clis.sh +0 -110
- package/templates/commonproject/template/.mise/scripts/unlink-project-skills-from-clis.sh +0 -45
- package/templates/hermes-agent/.codegraph/daemon.pid +0 -6
- package/templates/hermes-agent/.omo/run-continuation/ses_0e5b28303ffeXxL53hZjKggXDW.json +0 -10
- package/templates/hermes-agent/runtime-scaffold/bloodbank-consumer.py +0 -181
- package/templates/hermes-agent/template/.runtime-scaffold/bloodbank-consumer.py +0 -181
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delorenj/pjangler",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.25",
|
|
4
4
|
"description": "Project subsystem bootstrapper CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,14 +20,18 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "esbuild src/index.ts src/mcp-server.ts --bundle --packages=external --platform=node --format=esm --outdir=dist",
|
|
23
|
+
"check:audit:prod": "npm audit --omit=dev",
|
|
24
|
+
"check:lock": "node scripts/check-package-lock-parity.mjs",
|
|
25
|
+
"check:submodules": "node scripts/check-submodule-contract.mjs",
|
|
26
|
+
"check:tracked-secrets": "node scripts/check-tracked-secrets.mjs",
|
|
23
27
|
"start": "node dist/index.js",
|
|
24
28
|
"mcp": "node dist/mcp-server.js",
|
|
25
29
|
"typecheck": "tsc --noEmit",
|
|
26
|
-
"test": "node tests/parity-migrate-regressions.mjs && node tests/mcp-catalog-regressions.mjs && node tests/mcp-server-regressions.mjs && node tests/project-registry-regressions.mjs && node tests/pg-registry-regressions.mjs",
|
|
30
|
+
"test": "npm run check:lock && npm run check:submodules && npm run check:tracked-secrets && node tests/release-regressions.mjs && node tests/submodule-contract-regressions.mjs && node tests/secret-publication-gate-regressions.mjs && node tests/bmad-version-surface-regressions.mjs && node tests/bmad-transaction-regressions.mjs && node tests/parity-migrate-regressions.mjs && node tests/pjan-43-regressions.mjs && node tests/skillex-init-regressions.mjs && node tests/fleet-shared-bloodbank-regressions.mjs && node tests/mcp-catalog-regressions.mjs && node tests/mcp-server-regressions.mjs && node tests/project-registry-regressions.mjs && node tests/pg-registry-regressions.mjs",
|
|
27
31
|
"migrate:up": "node-pg-migrate --migrations-dir migrations up",
|
|
28
32
|
"migrate:down": "node-pg-migrate --migrations-dir migrations down",
|
|
29
33
|
"migrate:create": "node-pg-migrate --migrations-dir migrations create",
|
|
30
|
-
"prepublishOnly": "npm run build"
|
|
34
|
+
"prepublishOnly": "npm run check:lock && npm run check:submodules -- --remote --recursive --archive --npm && npm run build && npm run check:tracked-secrets"
|
|
31
35
|
},
|
|
32
36
|
"keywords": [
|
|
33
37
|
"cli",
|
|
@@ -52,5 +56,12 @@
|
|
|
52
56
|
"esbuild": "^0.25.0",
|
|
53
57
|
"node-pg-migrate": "^8.0.0",
|
|
54
58
|
"typescript": "^5"
|
|
59
|
+
},
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "https://github.com/delorenj/pjangler.git"
|
|
63
|
+
},
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"registry": "https://npm.pkg.github.com"
|
|
55
66
|
}
|
|
56
67
|
}
|
|
@@ -90,8 +90,9 @@ agent_hooks_layer:
|
|
|
90
90
|
default: true
|
|
91
91
|
when: false
|
|
92
92
|
|
|
93
|
-
# When agent_hooks_layer is false, omit the project-scoped hook tree
|
|
94
|
-
#
|
|
93
|
+
# When agent_hooks_layer is false, omit only the project-scoped hook tree. The
|
|
94
|
+
# skills manifest stays — sync-skills.py writes project-local CLI dirs and is safe
|
|
95
|
+
# even on machines that already run a global ~/.agents/hooks install.
|
|
95
96
|
# The `.copier-noop-never-matches` sentinel keeps every pattern non-empty when the
|
|
96
97
|
# layer is enabled, which copier requires.
|
|
97
98
|
_exclude:
|
|
@@ -105,8 +106,6 @@ _exclude:
|
|
|
105
106
|
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/hooks{% endif %}"
|
|
106
107
|
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/hooks/**{% endif %}"
|
|
107
108
|
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/local.example.json{% endif %}"
|
|
108
|
-
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.mise/scripts/link-project-skills-to-clis.sh{% endif %}"
|
|
109
|
-
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.mise/scripts/unlink-project-skills-from-clis.sh{% endif %}"
|
|
110
109
|
|
|
111
110
|
# --- Post-generation tasks ---
|
|
112
111
|
#
|
|
@@ -120,5 +119,8 @@ _tasks:
|
|
|
120
119
|
- "printf '\\n# Secrets + per-dev agent-hook/skill overrides (see .agents/local.example.json)\\n.env\\n.env.*\\n!.env.op\\n.agents/local.json\\n.kimi-code/\\n.lastagent\\n**/.claude/settings.local.json\\n' >> .gitignore"
|
|
121
120
|
- "ln -sf AGENTS.md CLAUDE.md"
|
|
122
121
|
- "ln -sf AGENTS.md GEMINI.md"
|
|
122
|
+
# Materialize the pinned Skillex BMAD manifest + symlink topology without
|
|
123
|
+
# copying pack content or disturbing project-specific, non-BMAD skills.
|
|
124
|
+
- "python3 .mise/scripts/provision-bmad-skills.py"
|
|
123
125
|
# Stamp the repo's absolute path into .project.json (the SOT) post-render.
|
|
124
126
|
- "python3 -c \"import json,os,pathlib; p=pathlib.Path('.project.json'); d=json.loads(p.read_text()); d['repo_path']=os.getcwd(); p.write_text(json.dumps(d,indent=2)+chr(10))\""
|
|
@@ -15,6 +15,7 @@ master writes zero bytes).
|
|
|
15
15
|
mise run hooks-sync # fan out the master -> claude + codex + hermes
|
|
16
16
|
mise run hooks-check # drift gate (read-only; used in CI)
|
|
17
17
|
mise run hooks-uninstall # remove codex + hermes injections
|
|
18
|
+
mise run skills-sync # sync .agents/skills.json -> local CLI skill dirs
|
|
18
19
|
mise run hindsight-setup # one-time: pull the shared CAF Hindsight key into .env
|
|
19
20
|
```
|
|
20
21
|
|
|
@@ -70,8 +71,7 @@ Copy [`.agents/local.example.json`](../local.example.json) → `.agents/local.js
|
|
|
70
71
|
"hooks": {
|
|
71
72
|
"disabled": ["hindsight-recall"], // hook ids — skipped at runtime, ALL agents
|
|
72
73
|
"disabled_agents": ["codex"] // claude|codex|hermes — codex/hermes injection skipped/removed
|
|
73
|
-
}
|
|
74
|
-
"skills": { "disabled": ["bmad-help"] } // skill dir names — not symlinked for you
|
|
74
|
+
}
|
|
75
75
|
}
|
|
76
76
|
```
|
|
77
77
|
|
|
@@ -83,32 +83,18 @@ Copy [`.agents/local.example.json`](../local.example.json) → `.agents/local.js
|
|
|
83
83
|
- **Disabled agents** are enforced at **install** time (codex/hermes injection is
|
|
84
84
|
skipped, and removed if previously installed). `CAF_HOOKS_SKIP_CODEX=1` is an
|
|
85
85
|
env shortcut for `disabled_agents:["codex"]`.
|
|
86
|
-
-
|
|
86
|
+
## Skill fan-out — `.agents/skills.json` → each CLI
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
`.agents/skills.json` is the project's skill manifest. `sync-skills.py --scope
|
|
89
|
+
project` resolves that manifest into project-local CLI dirs (for example
|
|
90
|
+
`./.codex/skills`, `./.hermes/skills`, `./.kimi-code/skills`) and honors
|
|
91
|
+
`inherit_global: true` so a dev's global `~/.agents/skills.json` loadout is
|
|
92
|
+
merged in automatically.
|
|
89
93
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
| CLI | target dir | scope |
|
|
96
|
-
|---|---|---|
|
|
97
|
-
| Codex | `~/.codex/skills` | **global** — link ours in, never clobber foreign entries, removed on `leave` |
|
|
98
|
-
| Kimi | `./.kimi-code/skills` | **local** — a project-scoped mirror we fully manage (stale real copies replaced with symlinks) |
|
|
99
|
-
|
|
100
|
-
Add a CLI = one `dir|scope` line. Per-dev control via `.agents/local.json`
|
|
101
|
-
`skills`:
|
|
102
|
-
|
|
103
|
-
- `disabled: [...]` — never link these; pruned from managed mirrors.
|
|
104
|
-
- `defer_to_global: true` — **only if you run a global `~/.agents/skills` system.**
|
|
105
|
-
Skips any project skill whose name also exists there, so your global copy wins
|
|
106
|
-
and you get **zero duplicates** (it even yields the slot in `~/.codex/skills`).
|
|
107
|
-
Teammates with no global layer leave it `false` (default) and **inherit the full
|
|
108
|
-
set**. Override the global dir with `AGENTS_GLOBAL_SKILLS_DIR`.
|
|
109
|
-
|
|
110
|
-
Tasks: `mise run skills-relink` (re-fan), `mise run link-project-skills-to-clis`,
|
|
111
|
-
`mise run unlink-project-skills-from-clis`.
|
|
94
|
+
- Project-local skills with the same name shadow the global ones.
|
|
95
|
+
- No `defer_to_global` flag or bash cleanup scripts are needed anymore.
|
|
96
|
+
- The manifest is the only hand-edited skill SSOT; run `mise run skills-sync`
|
|
97
|
+
after changing it, or just re-enter the repo.
|
|
112
98
|
|
|
113
99
|
## Hindsight credentials — `mise run hindsight-setup`
|
|
114
100
|
|
|
@@ -137,6 +123,7 @@ Without a key the hooks **no-op gracefully** — recall/retain just do nothing.
|
|
|
137
123
|
```
|
|
138
124
|
.agents/
|
|
139
125
|
local.example.json # per-dev override template (copy -> local.json, gitignored)
|
|
126
|
+
skills.json # project skill manifest (SSOT for sync-skills.py)
|
|
140
127
|
hooks/
|
|
141
128
|
hooks.master.json # SSOT — the only hand-edited config
|
|
142
129
|
sync.py # fan-out engine (--install / --uninstall / --check)
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
# Source this, then call:
|
|
5
5
|
# hook_disabled <hook-id> # true if .hooks.disabled[] contains the id
|
|
6
6
|
# agent_disabled <agent> # true if .hooks.disabled_agents[] contains the agent
|
|
7
|
-
# skill_disabled <skill-name> # true if .skills.disabled[] contains the name
|
|
8
7
|
#
|
|
9
8
|
# All FAIL OPEN (return 1 = "not disabled") when `.agents/local.json` or `jq` is
|
|
10
|
-
# absent, so a missing/garbled local config can never silently kill hooks
|
|
9
|
+
# absent, so a missing/garbled local config can never silently kill hooks.
|
|
11
10
|
#
|
|
12
11
|
# `.agents/local.json` is gitignored — each dev owns their own. See
|
|
13
12
|
# `.agents/local.example.json` for the schema.
|
|
@@ -30,22 +29,13 @@ _caf_listed() {
|
|
|
30
29
|
|
|
31
30
|
hook_disabled() { _caf_listed '.hooks.disabled' "$1"; }
|
|
32
31
|
agent_disabled() { _caf_listed '.hooks.disabled_agents' "$1"; }
|
|
33
|
-
skill_disabled() { _caf_listed '.skills.disabled' "$1"; }
|
|
34
32
|
|
|
35
|
-
# True if the dev opted to let their GLOBAL agent system (~/.agents/
|
|
36
|
-
#
|
|
37
|
-
# Teammates with no global layer omit this and inherit the full project set.
|
|
33
|
+
# True if the dev opted to let their GLOBAL agent system (~/.agents/hooks) provide
|
|
34
|
+
# the hook layer, so project-scoped per-user injections should be suppressed.
|
|
38
35
|
skills_defer_to_global() {
|
|
39
36
|
local f
|
|
40
37
|
f="$(_caf_local_json)" || return 1
|
|
41
38
|
[[ -f "$f" ]] || return 1
|
|
42
39
|
command -v jq >/dev/null 2>&1 || return 1
|
|
43
|
-
jq -e '.
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
# True if <skill-name> is provided by the global agent SSOT. `-e` follows the
|
|
47
|
-
# ~/.agents/skills symlink (-> skillex/skill-sets/global) and its entries.
|
|
48
|
-
skill_is_global() {
|
|
49
|
-
local name="$1" gdir="${AGENTS_GLOBAL_SKILLS_DIR:-$HOME/.agents/skills}"
|
|
50
|
-
[[ -e "${gdir}/${name}" ]]
|
|
40
|
+
jq -e '.hooks.defer_to_global == true' "$f" >/dev/null 2>&1
|
|
51
41
|
}
|
|
@@ -72,10 +72,10 @@ def load_local() -> dict:
|
|
|
72
72
|
(so even Claude's committed hooks honor them); this only needs disabled
|
|
73
73
|
AGENTS, which gate install. CAF_HOOKS_SKIP_CODEX=1 is an env shortcut.
|
|
74
74
|
|
|
75
|
-
`defer_to_global`
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
`hooks.defer_to_global` means "I already run these hooks from a global agent
|
|
76
|
+
system" — so the shared per-user injections (codex/kimi/hermes) are
|
|
77
|
+
suppressed and actively removed. Claude's committed repo settings are
|
|
78
|
+
harmless and left in place.
|
|
79
79
|
"""
|
|
80
80
|
disabled_agents: set[str] = set()
|
|
81
81
|
defer_to_global = False
|
|
@@ -84,9 +84,8 @@ def load_local() -> dict:
|
|
|
84
84
|
try:
|
|
85
85
|
data = json.loads(p.read_text() or "{}")
|
|
86
86
|
hooks_cfg = data.get("hooks") or {}
|
|
87
|
-
skills_cfg = data.get("skills") or {}
|
|
88
87
|
disabled_agents = set(hooks_cfg.get("disabled_agents") or [])
|
|
89
|
-
defer_to_global = bool(hooks_cfg.get("defer_to_global"))
|
|
88
|
+
defer_to_global = bool(hooks_cfg.get("defer_to_global"))
|
|
90
89
|
except (json.JSONDecodeError, OSError) as exc:
|
|
91
90
|
warn(f"ignoring malformed .agents/local.json: {exc}")
|
|
92
91
|
if os.environ.get("CAF_HOOKS_SKIP_CODEX") == "1":
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "PER-DEV LOCAL OVERRIDES — copy this file to .agents/local.json (gitignored) and edit. Lets you opt out of individual hooks
|
|
2
|
+
"$comment": "PER-DEV LOCAL OVERRIDES — copy this file to .agents/local.json (gitignored) and edit. Lets you opt out of individual hooks or whole injected agents without touching committed config. Hooks self-skip at RUNTIME via .agents/hooks/lib/hook-guard.sh (so even Claude's committed hooks honor it); codex/hermes injections additionally skip at INSTALL time. Re-run `mise run hooks-sync` (or re-cd into the repo) after editing.",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"$disabled_help": "Hook ids from .agents/hooks/hooks.master.json: skill-check-reminder, hindsight-recall, hindsight-retain, hindsight-session-end. Listed ids are skipped at runtime across ALL agents.",
|
|
5
5
|
"disabled": [],
|
|
6
6
|
"$disabled_agents_help": "Agent keys: claude, codex, kimi, hermes. Listed agents are NOT installed (codex/kimi/hermes injections are skipped/removed). Claude's hooks are committed and can't be fully removed per-dev — disable them individually via `disabled` instead.",
|
|
7
7
|
"disabled_agents": [],
|
|
8
|
-
"$defer_to_global_help": "Set true if you already run these hooks from a GLOBAL agent system (~/.agents/hooks). When true, sync.py suppresses AND removes the shared per-user injections (codex/kimi/hermes) so a project never double-injects into ~/.codex / ~/.kimi-code; Claude's committed repo settings are left in place.
|
|
9
|
-
"defer_to_global": false
|
|
10
|
-
},
|
|
11
|
-
"skills": {
|
|
12
|
-
"$disabled_help": "Skill directory names under .agents/skills/. Listed skills are NOT symlinked into any agent CLI dir for you, and are pruned from your managed mirrors.",
|
|
13
|
-
"disabled": [],
|
|
14
|
-
"$defer_to_global_help": "Set true ONLY if you run a global agent system at ~/.agents/skills. When true, the linker skips any project skill whose name also exists in your global SSOT, so your global copy wins and you get ZERO duplicates/conflicts (and yields the slot in shared dirs like ~/.codex/skills). Teammates with no global layer leave this false (the default) and inherit the FULL project skill set. Override the global dir with the AGENTS_GLOBAL_SKILLS_DIR env var.",
|
|
8
|
+
"$defer_to_global_help": "Set true if you already run these hooks from a GLOBAL agent system (~/.agents/hooks). When true, sync.py suppresses AND removes the shared per-user injections (codex/kimi/hermes) so a project never double-injects into ~/.codex / ~/.kimi-code; Claude's committed repo settings are left in place. On a machine with a global install, pjangler skips scaffolding this whole layer, so you rarely need to set this by hand.",
|
|
15
9
|
"defer_to_global": false
|
|
16
10
|
}
|
|
17
11
|
}
|