@delorenj/pjangler 1.2.21 → 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.
Files changed (63) hide show
  1. package/dist/index.js +1852 -368
  2. package/dist/mcp-server.js +1782 -296
  3. package/package.json +14 -3
  4. package/templates/commonproject/copier.yml +3 -0
  5. package/templates/commonproject/template/.mise/scripts/provision-bmad-skills.py +480 -0
  6. package/templates/commonproject/template/.mise/scripts/sync-skills.py +449 -0
  7. package/templates/commonproject/template/mise.toml.jinja +9 -2
  8. package/templates/commonproject/tests/test_provision_bmad_skills.py +203 -0
  9. package/templates/commonproject/tests/test_sync_skills_topology.py +120 -0
  10. package/templates/hermes-agent/README.md +70 -29
  11. package/templates/hermes-agent/copier.yml +9 -6
  12. package/templates/hermes-agent/docs/architecture.md +75 -51
  13. package/templates/hermes-agent/docs/fleet-control-plane/architecture.md +11 -6
  14. package/templates/hermes-agent/docs/fleet-control-plane/epics-and-stories.md +2 -2
  15. package/templates/hermes-agent/docs/fleet-control-plane/prd.md +2 -3
  16. package/templates/hermes-agent/docs/operations.md +179 -81
  17. package/templates/hermes-agent/docs/runbooks/runtime-checkpoint-repair.md +31 -171
  18. package/templates/hermes-agent/docs/sentinel/README.md +10 -10
  19. package/templates/hermes-agent/docs/sentinel/architecture.md +6 -8
  20. package/templates/hermes-agent/docs/sentinel/development.md +12 -15
  21. package/templates/hermes-agent/docs/sentinel.md +1 -1
  22. package/templates/hermes-agent/install-local.sh +41 -4
  23. package/templates/hermes-agent/runtime-scaffold/README.md +4 -2
  24. package/templates/hermes-agent/scripts/degit-runtime.sh +192 -0
  25. package/templates/hermes-agent/scripts/fleet-prune-debris.sh +128 -0
  26. package/templates/hermes-agent/scripts/fleet-sync.sh +164 -7
  27. package/templates/hermes-agent/scripts/hermes-runtime-templatize.py +321 -0
  28. package/templates/hermes-agent/scripts/migrate-profile-scoped-chat-secrets.py +136 -0
  29. package/templates/hermes-agent/scripts/momo-unify-agent.py +224 -0
  30. package/templates/hermes-agent/scripts/repair-runtime-checkpoint.sh +7 -119
  31. package/templates/hermes-agent/template/.gitignore.jinja +5 -2
  32. package/templates/hermes-agent/template/.runtime-scaffold/README.md +4 -2
  33. package/templates/hermes-agent/template/.scripts/00-banner.sh +1 -1
  34. package/templates/hermes-agent/template/.scripts/01-config.sh +3 -0
  35. package/templates/hermes-agent/template/.scripts/10-hermes-profile.sh +12 -1
  36. package/templates/hermes-agent/template/.scripts/20-runtime-repo.sh +55 -129
  37. package/templates/hermes-agent/template/.scripts/30-telegram.sh +276 -22
  38. package/templates/hermes-agent/template/.scripts/31-slack.sh +362 -0
  39. package/templates/hermes-agent/template/.scripts/60-bloodbank.sh +8 -66
  40. package/templates/hermes-agent/template/.scripts/70-systemd.sh +44 -30
  41. package/templates/hermes-agent/template/.scripts/80-registry.sh +93 -13
  42. package/templates/hermes-agent/template/.scripts/99-summary.sh +1 -4
  43. package/templates/hermes-agent/template/.scripts/_lib.sh +66 -1
  44. package/templates/hermes-agent/template/.scripts/checkpoint.sh +3 -2
  45. package/templates/hermes-agent/template/.scripts/config.example.toml +10 -10
  46. package/templates/hermes-agent/template/.scripts/heartbeat.sh +1 -1
  47. package/templates/hermes-agent/template/SOUL.md.jinja +2 -2
  48. package/templates/hermes-agent/template/hermes.jinja +6 -3
  49. package/templates/hermes-agent/template/role.yaml.jinja +24 -13
  50. package/templates/hermes-agent/tests/test_bloodbank_consumer_contract.py +429 -130
  51. package/templates/hermes-agent/tests/test_fleet_upgrade_contract.py +176 -0
  52. package/templates/hermes-agent/tests/test_launcher_chat_secret_isolation.py +85 -0
  53. package/templates/hermes-agent/tests/test_local_runtime_provisioning.py +130 -0
  54. package/templates/hermes-agent/tests/test_operator_docs_local_runtime_contract.py +132 -0
  55. package/templates/hermes-agent/tests/test_profile_env_detach_contract.py +14 -0
  56. package/templates/hermes-agent/tests/test_profile_scoped_chat_secrets.py +89 -0
  57. package/templates/hermes-agent/tests/test_repository_privacy_contract.py +32 -0
  58. package/templates/hermes-agent/tests/test_slack_provisioning.py +344 -0
  59. package/templates/hermes-agent/tests/test_telegram_provisioning.py +475 -0
  60. package/templates/hermes-agent/.codegraph/daemon.pid +0 -6
  61. package/templates/hermes-agent/.omo/run-continuation/ses_0e5b28303ffeXxL53hZjKggXDW.json +0 -10
  62. package/templates/hermes-agent/runtime-scaffold/bloodbank-consumer.py +0 -181
  63. package/templates/hermes-agent/template/.runtime-scaffold/bloodbank-consumer.py +0 -181
@@ -5,7 +5,6 @@ source "$(dirname "$0")/_lib.sh"
5
5
  load_role_env
6
6
 
7
7
  GW_UNIT="hermes-${AGENT_ID}-gateway.service"
8
- CSM_UNIT="hermes-${AGENT_ID}-consumer.service"
9
8
  HB_TIMER="hermes-${AGENT_ID}-heartbeat.timer"
10
9
 
11
10
  cat >&2 <<EOF
@@ -15,18 +14,16 @@ cat >&2 <<EOF
15
14
  │ Talk: @$BOT_HANDLE (Telegram DM)
16
15
  │ Shell: $ROLE_DIR/hermes chat "status"
17
16
  │ Board: $PLANE_BASE/$PLANE_WORKSPACE/projects/$(cat "$ROLE_DIR/.scripts/.plane-project-id" 2>/dev/null || echo "(skipped)")
18
- │ Runtime: gh:$RUNTIME_REPO (reconcile + checkpoint heartbeat)
17
+ │ Runtime: $ROLE_DIR/runtime (pure-local, ignored)
19
18
  │ Hermes bin: $HERMES_BIN
20
19
  │ Fleet env: $FLEET_ENV
21
20
 
22
21
  │ Start fleet daemons:
23
22
  │ systemctl --user start $GW_UNIT
24
- │ systemctl --user start $CSM_UNIT
25
23
  │ systemctl --user start $HB_TIMER
26
24
 
27
25
  │ Tail logs:
28
26
  │ journalctl --user -fu $GW_UNIT
29
- │ journalctl --user -fu $CSM_UNIT
30
27
 
31
28
  │ Fleet status:
32
29
  │ python3 -c "import yaml,pathlib; print(yaml.safe_dump(yaml.safe_load(pathlib.Path('$REGISTRY_FILE').read_text())['agents']))"
@@ -145,10 +145,17 @@ if [[ -f "$FLEET_ENV" ]]; then
145
145
  # shellcheck disable=SC1090
146
146
  source "$FLEET_ENV"
147
147
  fi
148
+ # Identity-bearing chat credentials are never fleet-scoped. Platform wiring
149
+ # steps capture explicit invocation values before sourcing this library and
150
+ # restore only those values afterward; all other provisioning steps stay clean.
151
+ unset TELEGRAM_BOT_TOKEN SLACK_BOT_TOKEN SLACK_APP_TOKEN
148
152
 
149
153
  # Tools we expect on the host
150
154
  HERMES_BIN="${HERMES_BIN:-${HERMES_FLEET_BIN:-$(config_get fleet.hermes_bin "$HOME/.hermes/hermes-agent/.venv/bin/hermes")}}"
151
155
  HERMES_AGENT_REPO="${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-$(config_get fleet.hermes_repo "$HOME/.hermes/hermes-agent")}}"
156
+ HERMES_RUNTIME_GIT_URL="${HERMES_RUNTIME_GIT_URL:-$(config_get fleet.hermes_git_url 'https://github.com/delorenj/hermes-agent.git')}"
157
+ HERMES_RUNTIME_GIT_REF="${HERMES_RUNTIME_GIT_REF:-$(config_get fleet.hermes_git_ref 'feature/PJAN-19-routing-publication')}"
158
+ HERMES_RUNTIME_GIT_SHA="${HERMES_RUNTIME_GIT_SHA:-$(config_get fleet.hermes_git_sha '113e1b182b6d72a7dd02a191f134a41668ceaf0e')}"
152
159
  HERMES_OAUTH_FILE="${HERMES_OAUTH_FILE:-${HERMES_FLEET_OAUTH_FILE:-$(config_get fleet.oauth_file "$HOME/.hermes/auth.json")}}"
153
160
  CODEX_HOME="${CODEX_HOME:-${HERMES_FLEET_CODEX_HOME:-$(config_get fleet.codex_home "$HOME/.codex")}}"
154
161
  # Prefer a scaffold vendored into this agent directory; fall back to the configured template path.
@@ -158,6 +165,29 @@ if [[ ! -d "$RUNTIME_SCAFFOLD_DIR" ]]; then
158
165
  fi
159
166
  REGISTRY_FILE="${REGISTRY_FILE:-${HERMES_FLEET_REGISTRY_FILE:-$(config_get fleet.registry_file "$HOME/.hermes/agents-registry.yaml")}}"
160
167
 
168
+ # Cross-process serialization for fleet identity claims and registry updates.
169
+ # The lock file may remain on disk; flock ownership is kernel-scoped, so a
170
+ # crashed provisioner cannot leave a permanently stale lock.
171
+ FLEET_LOCK_FD=""
172
+ fleet_lock_acquire() {
173
+ command -v flock >/dev/null 2>&1 || die "flock is required for safe fleet registry updates"
174
+ local lock_file="${REGISTRY_FILE}.lock"
175
+ mkdir -p "$(dirname "$lock_file")"
176
+ [[ ! -L "$lock_file" ]] || die "refusing fleet lock symlink: $lock_file"
177
+ exec {FLEET_LOCK_FD}>"$lock_file"
178
+ chmod 600 "$lock_file"
179
+ flock -w "${FLEET_LOCK_TIMEOUT_SECONDS:-30}" "$FLEET_LOCK_FD" \
180
+ || die "timed out waiting for fleet registry lock: $lock_file"
181
+ }
182
+
183
+ fleet_lock_release() {
184
+ if [[ "${FLEET_LOCK_FD:-}" =~ ^[0-9]+$ ]]; then
185
+ flock -u "$FLEET_LOCK_FD" 2>/dev/null || true
186
+ eval "exec ${FLEET_LOCK_FD}>&-"
187
+ fi
188
+ FLEET_LOCK_FD=""
189
+ }
190
+
161
191
  # Bloodbank / NATS
162
192
  BLOODBANK_NATS_HOST="${BLOODBANK_NATS_HOST:-$(config_get bloodbank.nats_host '127.0.0.1')}"
163
193
  BLOODBANK_NATS_PORT="${BLOODBANK_NATS_PORT:-$(config_get bloodbank.nats_port '4222')}"
@@ -167,7 +197,8 @@ BLOODBANK_COMPOSE_DIR="${BLOODBANK_COMPOSE_DIR:-$(config_get bloodbank.compose_d
167
197
  PLANE_BASE="${PLANE_BASE:-$(config_get plane.base 'https://plane.delo.sh')}"
168
198
  PLANE_API_KEY="${PLANE_API_KEY:-${PLANE_33GOD_API_KEY:-}}"
169
199
 
170
- export FLEET_ENV HERMES_BIN HERMES_AGENT_REPO HERMES_OAUTH_FILE CODEX_HOME \
200
+ export FLEET_ENV HERMES_BIN HERMES_AGENT_REPO HERMES_RUNTIME_GIT_URL \
201
+ HERMES_RUNTIME_GIT_REF HERMES_RUNTIME_GIT_SHA HERMES_OAUTH_FILE CODEX_HOME \
171
202
  RUNTIME_SCAFFOLD_DIR REGISTRY_FILE \
172
203
  BLOODBANK_NATS_HOST BLOODBANK_NATS_PORT BLOODBANK_COMPOSE_DIR \
173
204
  PLANE_BASE PLANE_API_KEY
@@ -180,6 +211,40 @@ systemd_user_available() {
180
211
  [[ "$state" =~ ^(running|degraded|starting|maintenance)$ ]]
181
212
  }
182
213
 
214
+ # Query one systemd user-unit state without conflating every non-zero exit with
215
+ # an inactive/disabled unit. Output is `ok|<state>` only for documented
216
+ # state/exit-code pairs; D-Bus, manager, and arbitrary query failures become
217
+ # `error|<safe summary>` so retirement callers can fail closed.
218
+ systemctl_user_unit_state() {
219
+ local query="$1" unit="$2" output rc first_line
220
+ command -v systemctl >/dev/null 2>&1 \
221
+ || { printf 'error|systemctl unavailable'; return 0; }
222
+ set +e
223
+ output="$(LC_ALL=C systemctl --user "$query" "$unit" 2>&1)"
224
+ rc=$?
225
+ set -e
226
+ first_line="${output%%$'\n'*}"
227
+ first_line="${first_line//$'\t'/ }"
228
+ first_line="${first_line//|/}"
229
+ case "$query:$rc:$first_line" in
230
+ is-active:0:active|is-active:0:reloading|is-active:0:activating|is-active:0:deactivating)
231
+ printf 'ok|%s' "$first_line" ;;
232
+ is-active:3:inactive|is-active:3:failed)
233
+ printf 'ok|%s' "$first_line" ;;
234
+ is-active:4:inactive)
235
+ printf 'ok|not-found' ;;
236
+ is-enabled:0:enabled|is-enabled:0:enabled-runtime|is-enabled:0:linked|is-enabled:0:linked-runtime|is-enabled:0:alias|is-enabled:0:static|is-enabled:0:indirect|is-enabled:0:generated|is-enabled:0:transient)
237
+ printf 'ok|%s' "$first_line" ;;
238
+ is-enabled:1:disabled|is-enabled:1:masked|is-enabled:1:masked-runtime)
239
+ printf 'ok|%s' "$first_line" ;;
240
+ is-enabled:4:not-found)
241
+ printf 'ok|not-found' ;;
242
+ *)
243
+ [[ -n "$first_line" ]] || first_line="exit $rc with no state"
244
+ printf 'error|%s' "$first_line" ;;
245
+ esac
246
+ }
247
+
183
248
  # Resolve project repo path (the repo that holds agents/hermes/<role>/).
184
249
  # Walk up from $ROLE_DIR until we find a git root that isn't us.
185
250
  project_repo_path() {
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env bash
2
- # Auto-checkpoint commit for the agent's runtime submodule.
2
+ # Legacy checkpoint compatibility for installations whose runtime is still a
3
+ # nested Git repository. Pure-local runtimes intentionally skip this script.
3
4
  # Idempotent — exits 0 with no commit if there are no changes.
4
5
  #
5
6
  # Secret-scan gate (PJAN): before committing, the staged diff is scanned for
@@ -11,7 +12,7 @@ set -euo pipefail
11
12
  RUNTIME_DIR="$(cd "$(dirname "$0")/../runtime" && pwd)"
12
13
  cd "$RUNTIME_DIR"
13
14
 
14
- # Skip if not a git repo (e.g. submodule not initialized)
15
+ # Skip when the pure-local runtime has no Git metadata.
15
16
  [[ -d .git || -f .git ]] || exit 0
16
17
 
17
18
  # Returns 0 when the staged diff looks clean, 1 when a likely secret is present.
@@ -13,8 +13,13 @@
13
13
  [fleet]
14
14
  # Absolute path to the shared Hermes executable every agent launcher execs.
15
15
  hermes_bin = "~/.hermes/hermes-agent/.venv/bin/hermes"
16
- # Checkout of the hermes-agent repo. Its .venv is used to install nats-py, etc.
16
+ # Checkout of the shared hermes-agent repo.
17
17
  hermes_repo = "~/.hermes/hermes-agent"
18
+ # Reviewed fleet runtime publication. Provisioning metadata and clean installs
19
+ # must agree on this fork/ref/SHA; do not substitute upstream main.
20
+ hermes_git_url = "https://github.com/delorenj/hermes-agent.git"
21
+ hermes_git_ref = "feature/PJAN-19-routing-publication"
22
+ hermes_git_sha = "113e1b182b6d72a7dd02a191f134a41668ceaf0e"
18
23
  # Fallback runtime scaffold dir — used only when an agent's vendored
19
24
  # ./.runtime-scaffold is missing.
20
25
  runtime_scaffold_dir = "~/code/hermes-agent-template/runtime-scaffold"
@@ -45,17 +50,12 @@ symlinked_runtime_skills = [
45
50
  ]
46
51
 
47
52
  [github]
48
- # Owner of the per-agent runtime repos (creates <owner>/agent-hm-<repo>-<role>).
49
- runtime_repo_owner = "delorenj"
53
+ # LEGACY INERT COMPATIBILITY METADATA ONLY. Older role manifests may still
54
+ # carry this owner field. Current provisioning does not create, attach,
55
+ # synchronize, restore, archive, or remove runtime storage from this value.
56
+ runtime_repo_owner = ""
50
57
 
51
58
  [plane]
52
59
  # Plane instance base URL and workspace slug (one project per agent).
53
60
  base = "https://plane.delo.sh"
54
61
  workspace = "33god"
55
-
56
- [bloodbank]
57
- # NATS endpoint the consumer connects to.
58
- nats_host = "127.0.0.1"
59
- nats_port = 4222
60
- # Where the bloodbank docker compose lives (used only for a hint message). ~ ok.
61
- compose_dir = "~/code/33GOD/bloodbank"
@@ -8,7 +8,7 @@
8
8
  # full pass executes the role's sentinel.prompt.md, which reasons about tickets
9
9
  # through the ticket-provider adapter (Linear | Plane | Trello) — never a
10
10
  # hardcoded backend. After the sentinel decision (skip OR full), it
11
- # opportunistically checkpoints the runtime submodule (commit+push) at most once
11
+ # opportunistically checkpoints only legacy nested-Git runtimes at most once
12
12
  # per HEARTBEAT_CHECKPOINT_MIN_INTERVAL_SECONDS, so memory/session state stays
13
13
  # durable without pushing every minute.
14
14
  set -euo pipefail
@@ -44,8 +44,8 @@ question — not three vague ones.
44
44
  You **MUST** emit a Bloodbank event for every consequential action you take.
45
45
  Envelope shape: CloudEvents 1.0, type `bloodbank.v1.<domain>.<entity>.<action>`,
46
46
  `actor.agent_id = {{ agent_id }}`, `producer = hermes-agent:{{ agent_id }}`,
47
- `source = hermes://agent/{{ agent_id }}`. The consumer in `./runtime/` already
48
- imports the envelope helper.
47
+ `source = hermes://agent/{{ agent_id }}`. Inbound commands arrive through the
48
+ fleet-shared Hermes gateway and are routed by `data.target_agent_id`.
49
49
 
50
50
  You **MUST NOT** invent new event `type` values. Bloodbank owns the naming
51
51
  contract at `~/code/33GOD/bloodbank/docs/event-naming.md` —
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # Launcher for {{ agent_id }}. Resolves HERMES_HOME to the runtime submodule
2
+ # Launcher for {{ agent_id }}. Resolves HERMES_HOME to the local runtime
3
3
  # and execs the shared fleet Hermes binary configured in ~/.hermes/fleet.env.
4
4
 
5
5
  set -euo pipefail
@@ -12,6 +12,9 @@ if [[ -f "$FLEET_ENV" ]]; then
12
12
  # shellcheck disable=SC1090
13
13
  source "$FLEET_ENV"
14
14
  fi
15
+ # Never pass an identity-bearing chat credential from shared fleet state into
16
+ # a profile process. Hermes loads the profile's own runtime/.env itself.
17
+ unset TELEGRAM_BOT_TOKEN SLACK_BOT_TOKEN SLACK_APP_TOKEN
15
18
 
16
19
  CONFIG="${HERMES_TEMPLATE_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/hermes-agent-template/config.toml}"
17
20
  config_get() {
@@ -49,8 +52,8 @@ HERMES_OAUTH_FILE="${HERMES_OAUTH_FILE:-${HERMES_FLEET_OAUTH_FILE:-$(config_get
49
52
  CODEX_HOME="${CODEX_HOME:-${HERMES_FLEET_CODEX_HOME:-$(config_get fleet.codex_home "$HOME/.codex")}}"
50
53
 
51
54
  if [[ ! -d "$HERMES_HOME" ]]; then
52
- echo "hermes: runtime submodule not initialized at $HERMES_HOME" >&2
53
- echo " fix: git submodule update --init --recursive" >&2
55
+ echo "hermes: local runtime not provisioned at $HERMES_HOME" >&2
56
+ echo " fix: run $ROLE_DIR/.scripts/20-runtime-repo.sh" >&2
54
57
  exit 1
55
58
  fi
56
59
 
@@ -1,6 +1,6 @@
1
1
  # Hermes agent role manifest. Tracked in the PROJECT repository.
2
2
  # The agent's actual state (memory, sessions, evolving SOUL) lives in the
3
- # runtime submodule. This file is the immutable contract for this role.
3
+ # ignored local runtime. This file is the immutable contract for this role.
4
4
 
5
5
  repo: {{ target_repo }}
6
6
  role: {{ role }}
@@ -14,12 +14,24 @@ model:
14
14
  name: "{{ model_name }}"
15
15
 
16
16
  # Hermes profile name. ~/.hermes/profiles/<name> symlinks to ./runtime/, so both
17
- # HERMES_HOME and `hermes --profile <name>` resolve to the runtime submodule.
17
+ # HERMES_HOME and `hermes --profile <name>` resolve to the local runtime.
18
18
  profile: {{ agent_id }}
19
19
 
20
20
  # Telegram bot identity (one bot per agent — see docs/architecture.md).
21
21
  telegram:
22
+ provisioning_status: "deferred"
22
23
  bot_username: "{{ bot_handle }}"
24
+ bot_id: ""
25
+
26
+ # Slack is opt-in. Credentials live only in runtime/.env; this block records
27
+ # safe provisioning state and the verified auth.test identity.
28
+ slack:
29
+ provisioning_status: "deferred"
30
+ team_id: ""
31
+ team_name: ""
32
+ bot_user_id: ""
33
+ bot_id: ""
34
+ bot_username: ""
23
35
 
24
36
  # Ticket-provider binding (linear | plane | trello).
25
37
  # The heartbeat reconciliation pass talks ONLY to this via .scripts/lib/ticket-provider.sh;
@@ -54,25 +66,24 @@ plane:
54
66
  # identifier is set by .scripts/42-ticket-provider.sh after creation (plane only)
55
67
  identifier: ""
56
68
 
57
- # Bloodbank wiring (consumed + produced subjects).
69
+ # Bloodbank ingress is owned by one fleet-shared Hermes gateway. The gateway
70
+ # reads the fleet registry and routes canonical commands by target_agent_id;
71
+ # this profile does not install its own NATS consumer or inbox bridge.
58
72
  bloodbank:
59
- subscribe:
60
- - "bloodbank.evt.v1.repo.>"
61
- - "bloodbank.cmd.v1.agent.>"
62
- routing:
63
- repo: "{{ target_repo }}"
64
- target_agent_id: "{{ agent_id }}"
73
+ gateway_scope: fleet
74
+ target_agent_id: "{{ agent_id }}"
65
75
  producer: "hermes-agent:{{ agent_id }}"
66
76
 
67
- # Runtime repo (git-tracked HERMES_HOME, auto-checkpointed).
77
+ # Pure-local HERMES_HOME. The legacy GitHub identity remains metadata-only for
78
+ # locating old archives; provisioning never creates or attaches a submodule.
68
79
  runtime:
69
80
  # Empty owner -> resolved from config.toml [github].runtime_repo_owner.
70
81
  github_owner: "{{ runtime_repo_owner }}"
71
82
  github_repo: "{{ runtime_repo }}"
72
- submodule_path: "./runtime"
83
+ local_path: "./runtime"
73
84
  checkpoint:
74
- cadence: "heartbeat"
75
- on_session_end: true
85
+ cadence: "disabled"
86
+ on_session_end: false
76
87
 
77
88
  # Provenance — managed by the template, do not hand-edit.
78
89
  provisioned_at: "{{ '%Y-%m-%dT%H:%M:%SZ' | strftime }}"