kijito-tools 0.2.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.
Files changed (104) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +6 -0
  3. package/README.md +220 -0
  4. package/bin/cli.js +34 -0
  5. package/install.sh +161 -0
  6. package/package.json +50 -0
  7. package/providers/_shared/wake-core.mjs +358 -0
  8. package/providers/claude/CLAUDE.md.snippet +31 -0
  9. package/providers/claude/install.sh +186 -0
  10. package/providers/claude/scripts/arm-session.sh +66 -0
  11. package/providers/claude/scripts/claude-armed.sh +101 -0
  12. package/providers/claude/scripts/heartbeat-watchdog.sh +209 -0
  13. package/providers/claude/scripts/inbox-selftest.sh +277 -0
  14. package/providers/claude/scripts/kijito-persona-lib.sh +94 -0
  15. package/providers/claude/scripts/kijito-qa-pass.sh +12 -0
  16. package/providers/claude/scripts/lifecycle-lib.sh +167 -0
  17. package/providers/claude/scripts/myctx.sh +46 -0
  18. package/providers/claude/scripts/self-clear.sh +134 -0
  19. package/providers/claude/scripts/session-autosend.sh +85 -0
  20. package/providers/claude/scripts/session-catchup-hint.sh +330 -0
  21. package/providers/claude/scripts/statusline-context.sh +67 -0
  22. package/providers/claude/skills/kijito-qa-memory/SKILL.md +110 -0
  23. package/providers/claude/skills/kijito-recall/SKILL.md +53 -0
  24. package/providers/claude/skills/kijito-start/SKILL.md +122 -0
  25. package/providers/claude/wiring/README.md +93 -0
  26. package/providers/claude/wiring/kijito-heartbeat@.service +21 -0
  27. package/providers/codex/README.md +75 -0
  28. package/providers/codex/codex-kijito-parity-plan.md +265 -0
  29. package/providers/codex/docs-codex-setup.md +64 -0
  30. package/providers/codex/install.mjs +184 -0
  31. package/providers/codex/n0-capability-probe-protocol.md +472 -0
  32. package/providers/codex/n0-harness/README.md +57 -0
  33. package/providers/codex/n0-harness/cli.mjs +58 -0
  34. package/providers/codex/n0-harness/evidence-manifest.mjs +77 -0
  35. package/providers/codex/n0-harness/fixture.mjs +279 -0
  36. package/providers/codex/n0-harness/lib.mjs +141 -0
  37. package/providers/codex/n0-harness/manifest.mjs +36 -0
  38. package/providers/codex/n0-harness/oracle.mjs +464 -0
  39. package/providers/codex/n0-harness/parser.mjs +200 -0
  40. package/providers/codex/n0-harness/prompt.mjs +43 -0
  41. package/providers/codex/n0-harness/snapshot.mjs +120 -0
  42. package/providers/codex/n0-harness/specimen.mjs +37 -0
  43. package/providers/codex/notify/kijito-notify-count.mjs +117 -0
  44. package/providers/codex/notify/kijito-notify-count.test.mjs +76 -0
  45. package/providers/codex/plans/gate4-battery-log.md +184 -0
  46. package/providers/codex/plans/gate4-battery-protocol.md +43 -0
  47. package/providers/codex/plans/hive-user-first-plan-QA.md +34 -0
  48. package/providers/codex/plans/hive-user-first-plan.md +247 -0
  49. package/providers/codex/release-manifest.json +53 -0
  50. package/providers/codex/same-chat-continuation-plan-gate.md +235 -0
  51. package/providers/codex/same-chat-continuation-plan.md +458 -0
  52. package/providers/codex/skills/kijito-qa-memory/SKILL.md +193 -0
  53. package/providers/codex/skills/kijito-qa-memory/agents/openai.yaml +4 -0
  54. package/providers/codex/skills/kijito-recall/SKILL.md +53 -0
  55. package/providers/codex/skills/kijito-start/SKILL.md +173 -0
  56. package/providers/codex/skills/kijito-start/agents/openai.yaml +4 -0
  57. package/providers/codex/test/n0-cli-refusal.test.mjs +31 -0
  58. package/providers/codex/test/n0-counterexample-matrix.test.mjs +118 -0
  59. package/providers/codex/test/n0-guard-census-core.mjs +1372 -0
  60. package/providers/codex/test/n0-guard-census.json +35479 -0
  61. package/providers/codex/test/n0-guard-census.mjs +31 -0
  62. package/providers/codex/test/n0-guard-census.test.mjs +374 -0
  63. package/providers/codex/test/n0-guard-counterexamples.mjs +1068 -0
  64. package/providers/codex/test/n0-guard-independent-projection.mjs +70 -0
  65. package/providers/codex/test/n0-guard-independent-projection.test.mjs +53 -0
  66. package/providers/codex/test/n0-guard-manifest-author.mjs +424 -0
  67. package/providers/codex/test/n0-guard-mutation-operators.test.mjs +244 -0
  68. package/providers/codex/test/n0-guard-mutation-runner.mjs +599 -0
  69. package/providers/codex/test/n0-guard-remainder-classes.test.mjs +314 -0
  70. package/providers/codex/test/n0-guard-sanitizer-pairs.test.mjs +68 -0
  71. package/providers/codex/test/n0-guard-shared-context-predicates.test.mjs +84 -0
  72. package/providers/codex/test/n0-harness.test.mjs +553 -0
  73. package/providers/codex/test/n0-notable-regressions.test.mjs +70 -0
  74. package/providers/codex/test/n0-subject-boundary.mjs +97 -0
  75. package/providers/codex/test/n0-subject-boundary.test.mjs +72 -0
  76. package/providers/codex/test/same-chat-plan-preflight.sh +167 -0
  77. package/providers/codex/tools/refresh-manifest.mjs +81 -0
  78. package/providers/codex/wake-helper/TRANSPORT-NOTES.md +25 -0
  79. package/providers/codex/wake-helper/integration.test.mjs +285 -0
  80. package/providers/codex/wake-helper/kijito-wake-helper.mjs +488 -0
  81. package/providers/codex/wake-helper/kijito-wake-helper.test.mjs +128 -0
  82. package/providers/codex/wake-helper/mock-daemon.mjs +64 -0
  83. package/providers/codex/wake-helper/status-probe.mjs +45 -0
  84. package/providers/codex/wake-helper/ws-uds.mjs +153 -0
  85. package/providers/monitor/.github/workflows/publish-npm.yml +38 -0
  86. package/providers/monitor/.github/workflows/publish-pypi.yml +30 -0
  87. package/providers/monitor/CHANGELOG.md +465 -0
  88. package/providers/monitor/IMPORT-PROVENANCE.md +68 -0
  89. package/providers/monitor/LICENSE +202 -0
  90. package/providers/monitor/NOTICE +7 -0
  91. package/providers/monitor/OPAQUE-OUTPUT-ENFORCEMENT.md +45 -0
  92. package/providers/monitor/README.md +571 -0
  93. package/providers/monitor/RELEASING.md +125 -0
  94. package/providers/monitor/arm-hive-monitor.sh +13 -0
  95. package/providers/monitor/bin/cli.js +43 -0
  96. package/providers/monitor/com.kijito.inbox-monitor.plist.template +59 -0
  97. package/providers/monitor/docs/DESIGN.md +984 -0
  98. package/providers/monitor/kijito-inbox-monitor@.service.template +95 -0
  99. package/providers/monitor/kijito_inbox_monitor.py +3666 -0
  100. package/providers/monitor/package.json +35 -0
  101. package/providers/monitor/pyproject.toml +42 -0
  102. package/providers/monitor/scripts/mutation-check.py +399 -0
  103. package/providers/monitor/scripts/prepublish-gate.sh +284 -0
  104. package/providers/monitor/test_kijito_monitor.py +5609 -0
@@ -0,0 +1,125 @@
1
+ # Releasing
2
+
3
+ Releases are automated with GitHub Actions Trusted Publishing (OIDC). No API tokens are stored
4
+ anywhere. Pushing a version tag publishes to both PyPI and npm, with provenance attached.
5
+
6
+ ## Cut a release
7
+
8
+ 1. Bump the version to the same value in all THREE places:
9
+ - `pyproject.toml` -> `[project] version`
10
+ - `package.json` -> `"version"`
11
+ - `kijito_inbox_monitor.py` -> `__version__`
12
+ The third is easy to miss and this file used to omit it. It is not cosmetic: `__version__` builds
13
+ the `User-Agent` the watcher sends, so leaving it behind makes every request report the previous
14
+ release, and server-side logs then attribute traffic to a version that is not running.
15
+ Verify with: `grep -n '^version\|"version"\|^__version__' pyproject.toml package.json kijito_inbox_monitor.py`
16
+ 2. Add a section for the new version to `CHANGELOG.md`.
17
+ 3. Run the pre-publish gates. ALL FOUR (typography, memory-ids, path-escapes, private-detail) must report
18
+ clean, the exemption line must show nothing you expected to be inspected, and the canary must prove
19
+ the gate can still fire - a gate that cannot fail is worse than no gate, because it certifies:
20
+ ```sh
21
+ ./scripts/prepublish-gate.sh
22
+ ```
23
+ It re-derives the file list from `git ls-files` on purpose. A hardcoded list has been wrong twice,
24
+ and PyPI/npm metadata is immutable per version, so the descriptions in `pyproject.toml` and
25
+ `package.json` are exactly the text you cannot fix later.
26
+ 4. Commit, tag, and push:
27
+ ```sh
28
+ git commit -am "release: vX.Y.Z"
29
+ git tag -a vX.Y.Z -m "kijito-inbox-monitor vX.Y.Z"
30
+ git push origin main --follow-tags
31
+ ```
32
+ 5. The tag triggers `.github/workflows/publish-pypi.yml` and `publish-npm.yml`. Both publish
33
+ over OIDC, no tokens.
34
+ 6. Confirm BOTH registries independently - never trust the workflow's own report, because a
35
+ half-failure (one registry published, the other not) is the case that actually happens and a
36
+ version can never be re-uploaded:
37
+ ```sh
38
+ gh run watch
39
+ npm view kijito-inbox-monitor version
40
+ curl -s https://pypi.org/pypi/kijito-inbox-monitor/json | python3 -c 'import json,sys; print(json.load(sys.stdin)["info"]["version"])'
41
+ ```
42
+ 7. Create the GitHub Release for the tag:
43
+ ```sh
44
+ gh release create vX.Y.Z --title vX.Y.Z --notes-file <(sed -n '/## \[X.Y.Z\]/,/## \[/p' CHANGELOG.md)
45
+ ```
46
+ That `sed` range is INCLUSIVE, so it trails the next version's heading into the notes. Strip the
47
+ last line, or check the rendered release before you walk away.
48
+ 8. ⚠️ **PUBLISHING DOES NOT UPDATE THE FLEET, AND AFTER STEP 2 A RESTART ALONE DOES NOTHING EITHER.**
49
+ ⚠️ "STEP 2" HERE MEANS THE RECOVERY PLAN'S STEP 2 (repoint the launchd plist at a pinned artifact),
50
+ NOT step 2 of this file.
51
+ Once the plist points at a pinned artifact, the producer no longer reads the working tree, so a green PyPI/npm publish AND a restart both leave it on the OLD bytes. You must REBUILD /
52
+ REINSTALL the pinned artifact at the new version, repoint the plist, restart, and RE-VERIFY the health
53
+ block (exactly one process, `launchctl list` status 0, no PINNED/CORRUPT state files, zero
54
+ `bounded-window` alerts, heartbeat within ~2 min). `launchctl bootstrap` is not atomic - never assume
55
+ it came back.
56
+ ★ **THIS IS DONE-WHEN #7 AND THE RELEASE IS NOT COMPLETE WITHOUT IT.** Items 1-6 can all pass while the
57
+ fleet's only mail producer still runs the PRE-RELEASE artifact.
58
+
59
+ ## The producer runs a PINNED ARTIFACT - a restart deploys NOTHING
60
+
61
+ ✔ DONE 2026-07-27. `com.kijito.inbox-monitor` executes a read-only artifact under
62
+ `~/.local/share/kijito-inbox-monitor/versions/<sha>/`, extracted with `git show <sha>:...` and checksum-
63
+ asserted equal to the commit; both `ProgramArguments[2]` and `WorkingDirectory` point there. Confirm with
64
+ `plutil -p ~/Library/LaunchAgents/com.kijito.inbox-monitor.plist`.
65
+ ⚠️⚠️ **THE CONSEQUENCE INVERTS THE OLD RULE, AND THIS IS THE DANGEROUS PART.** Editing the working tree,
66
+ switching branches or committing changes NOTHING about what the fleet runs, and neither does a restart.
67
+ **Anyone acting on the old "a restart IS the deploy" rule will deploy nothing and believe they deployed** -
68
+ a no-op deploy and a successful one produce identical evidence (process up, status 0, heartbeat fresh,
69
+ mail flowing), because those are properties of whatever is running, not of what you intended to run.
70
+ ★ TO DEPLOY: rebuild the artifact at the NEW sha, repoint BOTH plist paths, `bootout` -> wait for the pid
71
+ to VANISH (~50s) -> `bootstrap`, then **assert the running process is that sha**. State the requirement as a
72
+ PROPERTY, because the operator's own tooling is not part of this package:
73
+ THE RUNNING ARGV MUST CARRY THE EXPECTED SHA. Nothing else settles it.
74
+ A self-contained check, which needs only a shell and a running producer:
75
+ ```sh
76
+ # SHORT sha - the artifact directories are 7-char. A full 40-char rev-parse of the CORRECT running
77
+ # commit FAILS this check, and it fails mid-release, which is exactly when a false alarm gets
78
+ # "fixed" by loosening the check that was right.
79
+ sha=$(git rev-parse --short <ref>)
80
+ procs=$(pgrep -f 'kijito_inbox_monitor\.py' || true)
81
+ n=$(printf '%s' "$procs" | grep -c . || true)
82
+ [ "$n" -eq 1 ] || { echo "FAIL: expected exactly 1 producer, found $n"; exit 1; }
83
+ ps -o command= -p "$procs" | grep -q "/versions/$sha/" \
84
+ && echo "ok: the single running producer carries $sha" \
85
+ || { echo "FAIL: the running argv does not carry $sha"; exit 1; }
86
+ ```
87
+ ⚠️ The process COUNT is asserted first and is not decoration: with an old and a new producer both alive, a
88
+ bare match on the expected sha SUCCEEDS while the fleet is still partly serving the old bytes. Verified in
89
+ all three directions (right sha, wrong sha, two processes) before being written down.
90
+ Health alone cannot tell a successful deploy from a no-op one; only naming the expected sha can.
91
+ ⚠️ This file previously named a helper script by a RELATIVE PATH that pointed OUTSIDE the repository, so a
92
+ clone could not run the gate this document mandates - and the path would silently resolve to whatever
93
+ happened to sit above the checkout. The fleet operator's richer health tool lives in the private workspace
94
+ alongside this repo, deliberately outside it; it is not required to perform a release, and no public
95
+ instruction may depend on a path a clone does not contain.
96
+ Before touching launchctl: `bootout` + `bootstrap` (never `kickstart`), never back-to-back (they race ->
97
+ "Bootstrap failed: 5" leaving NO service), SIGTERM takes ~50s, copy the current plist aside as a rollback
98
+ FIRST, and announce the restart to the hive - this is the fleet's only mail producer.
99
+ ⚠️ "Released artifact" does NOT mean a PyPI release. Reading it that way made the plan circular (repoint
100
+ needs a release -> release needs a GREEN audit -> the audit was meant to follow the repoint). Install the
101
+ audited SHA as a LOCAL versioned artifact: a built wheel, or a read-only checkout at the tag.
102
+ (This section previously said the producer "does not run this package (yet)" and "currently executes the
103
+ WORKING TREE directly", four lines after item 8 said the opposite. It was stale from the moment step 2
104
+ landed, and the stale half was the one that would cause a silent no-op deploy - re-audit 11, F4.)
105
+
106
+ ## One-time setup (already done for 0.1.0)
107
+
108
+ - PyPI: a Trusted Publisher is configured for the project (this repo + `publish-pypi.yml` + the
109
+ `pypi` environment).
110
+ - npm: a Trusted Publisher is configured for the package.
111
+ - GitHub: a `pypi` environment exists in repository settings.
112
+
113
+ ## Notes
114
+
115
+ - A published version can never be re-uploaded. To fix a mistake, bump to the next patch version.
116
+ - npm cannot use OIDC for the very first publish of a brand-new package, so that one is manual;
117
+ every version after it publishes over OIDC.
118
+ - Keep public-facing text free of em-dashes and internal references before tagging. That includes
119
+ the README, the design doc, the script docstring and `--help` text, and the PyPI/npm
120
+ descriptions, not just Markdown. Step 3 enforces this; the prose here is the rationale, not the
121
+ check. A gate that lives only in prose does not run.
122
+ - Beware the shell when writing any gate by hand. `FILES=$(git ls-files); grep -nE ... $FILES` does
123
+ NOT word-split in zsh: grep receives one nonexistent filename, exits non-zero, and an
124
+ `|| echo clean` reports success while having inspected nothing. That exact false clean was
125
+ observed in this repo. The script pipes NUL-delimited paths into `xargs -0` for this reason.
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ DIR=$(CDPATH= cd "$(dirname "$0")" && pwd)
5
+ STATE_FILE="${KIJITOMON_STATE_FILE:-$HOME/.cache/kijito-inbox-monitor/hive.json}"
6
+
7
+ # Default to stdout (interactive). For a SUPERVISED producer, set KIJITOMON_EVENTS_FILE to an owned,
8
+ # size-rotated events log that survives rotation (see --events-file). Do not redirect stdout to the log.
9
+ set -- --state-file "$STATE_FILE" "$@"
10
+ [ -n "${KIJITOMON_EVENTS_FILE_TEMPLATE:-}" ] && set -- --events-file-template "$KIJITOMON_EVENTS_FILE_TEMPLATE" "$@"
11
+ [ -n "${KIJITOMON_EVENTS_FILE:-}" ] && set -- --events-file "$KIJITOMON_EVENTS_FILE" "$@"
12
+
13
+ exec python3 -u "$DIR/kijito_inbox_monitor.py" "$@"
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // kijito-inbox-monitor on npm is a SIGNPOST, not an installer.
4
+ //
5
+ // The real tool is a pure-Python package on PyPI. Building a Node installer for a
6
+ // Python tool is fragile (it would need Node AND Python AND pipx all on PATH), so
7
+ // this package does not install anything. It only:
8
+ // 1. delegates to the Python tool via uvx / pipx run if either is present, or
9
+ // 2. prints how to install it and exits non-zero.
10
+ // There is deliberately no postinstall hook (npm v12 disables install lifecycle
11
+ // scripts by default, and that hook is the supply-chain-worm pattern).
12
+
13
+ const { spawnSync } = require('node:child_process');
14
+
15
+ function present(cmd) {
16
+ const r = spawnSync(cmd, ['--version'], { stdio: 'ignore' });
17
+ return !r.error && (r.status === 0 || r.status === null);
18
+ }
19
+
20
+ const args = process.argv.slice(2);
21
+
22
+ // Prefer uvx (fast), then `pipx run`. Both run the published PyPI package without a
23
+ // persistent install, which is the right zero-friction path for a one-off invocation.
24
+ for (const [cmd, prefix] of [['uvx', []], ['pipx', ['run']]]) {
25
+ if (present(cmd)) {
26
+ const r = spawnSync(cmd, [...prefix, 'kijito-inbox-monitor', ...args], {
27
+ stdio: 'inherit',
28
+ env: process.env,
29
+ });
30
+ process.exit(r.status ?? 1);
31
+ }
32
+ }
33
+
34
+ process.stderr.write(
35
+ 'kijito-inbox-monitor is a Python tool; this npm package is only a pointer to it.\n' +
36
+ 'Install the real tool with one of:\n' +
37
+ ' pipx install kijito-inbox-monitor\n' +
38
+ ' uv tool install kijito-inbox-monitor\n' +
39
+ ' pip install kijito-inbox-monitor\n' +
40
+ 'then run: kijito-inbox-monitor --help\n' +
41
+ 'Docs: https://github.com/KijitoAI/kijito-inbox-monitor\n'
42
+ );
43
+ process.exit(1);
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ TEMPLATE - substitute the three placeholders before loading. This file is NOT loadable as-is, and
4
+ that is deliberate: it previously shipped one operator's absolute home directory baked into seven
5
+ paths, which is useless to you and leaks the layout of a machine you do not have.
6
+
7
+ __PYTHON__ absolute path to the interpreter, e.g. /usr/bin/python3 or /opt/homebrew/bin/python3
8
+ (launchd does not search PATH, so this must be absolute)
9
+ __PROGRAM__ absolute path to the kijito_inbox_monitor.py you want to run
10
+ __HOME__ your home directory (the value of $HOME)
11
+
12
+ Install:
13
+ sed -e 's|__PYTHON__|'"$(command -v python3)"'|' \
14
+ -e 's|__PROGRAM__|'"$HOME/.local/share/kijito-inbox-monitor/versions/<sha>/kijito_inbox_monitor.py"'|' \
15
+ -e 's|__HOME__|'"$HOME"'|' \
16
+ com.kijito.inbox-monitor.plist.template > ~/Library/LaunchAgents/com.kijito.inbox-monitor.plist
17
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.kijito.inbox-monitor.plist
18
+
19
+ ⚠️ POINT __PROGRAM__ AT A PINNED, READ-ONLY ARTIFACT, NOT AT A WORKING TREE. If it points at a
20
+ checkout, "deploying" by publishing a package leaves the producer on whatever the tree happens to
21
+ contain, and a restart does not change that - you will believe you deployed and have not. Rebuild
22
+ the artifact, repoint this file, restart, then assert the running argv carries the expected short
23
+ sha (RELEASING.md has the check).
24
+
25
+ ⚠️ The token file must be mode 0600; the producer refuses a world-readable one.
26
+ -->
27
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
28
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
29
+ <plist version="1.0">
30
+ <dict>
31
+ <key>Label</key>
32
+ <string>com.kijito.inbox-monitor</string>
33
+ <key>ProgramArguments</key>
34
+ <array>
35
+ <string>__PYTHON__</string>
36
+ <string>-u</string>
37
+ <string>__PROGRAM__</string>
38
+ <string>--token-file</string>
39
+ <string>__HOME__/.config/kijito-inbox-monitor/token</string>
40
+ <string>--state-file</string>
41
+ <string>__HOME__/.cache/kijito-inbox-monitor/hive.json</string>
42
+ <string>--events-file-template</string>
43
+ <string>__HOME__/.cache/kijito-inbox-monitor/events.{persona}.ndjson</string>
44
+ <string>--heartbeat</string>
45
+ <string>120</string>
46
+ <string>--no-content</string>
47
+ </array>
48
+ <key>StandardOutPath</key>
49
+ <string>__HOME__/.cache/kijito-inbox-monitor/monitor.out</string>
50
+ <key>StandardErrorPath</key>
51
+ <string>__HOME__/.cache/kijito-inbox-monitor/monitor.err</string>
52
+ <key>RunAtLoad</key>
53
+ <true/>
54
+ <key>KeepAlive</key>
55
+ <true/>
56
+ <key>ThrottleInterval</key>
57
+ <integer>10</integer>
58
+ </dict>
59
+ </plist>