forge-orkes 0.63.0 → 0.64.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 (23) hide show
  1. package/package.json +1 -1
  2. package/template/.claude/hooks/forge-release-fold.sh +9 -1
  3. package/template/.claude/skills/jarvis/SKILL.md +204 -0
  4. package/template/.forge/checks/forge-board-render.sh +11 -5
  5. package/template/.forge/checks/forge-jarvis-answer.sh +79 -0
  6. package/template/.forge/checks/forge-jarvis-awareness.sh +128 -0
  7. package/template/.forge/checks/forge-jarvis-bridge-clean.sh +130 -0
  8. package/template/.forge/checks/forge-jarvis-dispatch.sh +176 -0
  9. package/template/.forge/checks/forge-jarvis-instruments.sh +146 -0
  10. package/template/.forge/checks/forge-jarvis-notify-logonly.sh +40 -0
  11. package/template/.forge/checks/forge-jarvis-promote.sh +103 -0
  12. package/template/.forge/checks/forge-jarvis-prwatch.sh +92 -0
  13. package/template/.forge/checks/forge-jarvis-relay.sh +215 -0
  14. package/template/.forge/checks/forge-jarvis.sh +160 -0
  15. package/template/.forge/checks/tests/forge-jarvis-answer.test.sh +75 -0
  16. package/template/.forge/checks/tests/forge-jarvis-bridge-clean.test.sh +94 -0
  17. package/template/.forge/checks/tests/forge-jarvis-dispatch.test.sh +162 -0
  18. package/template/.forge/checks/tests/forge-jarvis-instruments.test.sh +64 -0
  19. package/template/.forge/checks/tests/forge-jarvis-promote.test.sh +102 -0
  20. package/template/.forge/checks/tests/forge-jarvis-prwatch.test.sh +66 -0
  21. package/template/.forge/checks/tests/forge-jarvis-relay.test.sh +135 -0
  22. package/template/.forge/checks/tests/forge-jarvis.test.sh +122 -0
  23. package/template/.forge/templates/project.yml +11 -0
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env sh
2
+ # Fixture-repo test suite for .forge/checks/forge-jarvis.sh --dry-run (m-37, Brief-R2 step 4 B2).
3
+ #
4
+ # Contract under test (handoff-step4-jarvis.md REV2 B2 + operator ruling 6 +
5
+ # runbook-B1-live-test-recon.md "After B1" bake-ins):
6
+ # --dry-run prints the fully resolved launch command and NEVER executes:
7
+ # caffeinate -s claude remote-control --name <sticky> --spawn worktree --capacity <N>
8
+ # Name: jarvis-<repo-basename> (from the git COMMON dir — stable across worktrees),
9
+ # + optional suffix from jarvis.name_suffix, overridden per machine by
10
+ # FORGE_JARVIS_NAME_SUFFIX (probe ii: the sticky name is the only discoverability
11
+ # anchor). Capacity: --capacity flag > jarvis.capacity > 4. NO token export ever
12
+ # (probe iv — asserted here as an env-name absence in the output). Refusals:
13
+ # jarvis.enabled: false, or not a git repo → non-zero exit, NO command on stdout.
14
+ #
15
+ # Builds throwaway git repos in a mktemp dir, offline by construction; only ever
16
+ # invokes --dry-run, so `claude`/`caffeinate` need not exist (dry-run is pure
17
+ # resolution — that determinism is itself part of the contract).
18
+ #
19
+ # Usage: ./.forge/checks/tests/forge-jarvis.test.sh
20
+ # RED-phase friendly: a missing/non-executable script fails every case, exits non-zero.
21
+ set -u
22
+
23
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
24
+ JARVIS="$SCRIPT_DIR/../forge-jarvis.sh"
25
+
26
+ [ -f "$JARVIS" ] || printf 'NOTE: %s missing — RED phase, every case should FAIL\n' "$JARVIS" >&2
27
+
28
+ ROOT="$(mktemp -d)"
29
+ trap 'rm -rf "$ROOT"' EXIT INT TERM
30
+ GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null
31
+ export GIT_CONFIG_GLOBAL GIT_CONFIG_SYSTEM
32
+ unset FORGE_JARVIS_NAME_SUFFIX 2>/dev/null || true
33
+
34
+ PASSED=0; FAILED=0
35
+ ok() { PASSED=$((PASSED+1)); printf ' ok %s\n' "$1"; }
36
+ bad() { FAILED=$((FAILED+1)); printf ' FAIL %s\n %s\n' "$1" "$2"; }
37
+
38
+ # --- fixture repo (basename "proj" → expected sticky base jarvis-proj) -------
39
+ REPO="$ROOT/proj"
40
+ mkdir -p "$REPO/.forge"
41
+ git -C "$ROOT" init -q -b main "$REPO"
42
+
43
+ # 1. default derivation — no jarvis: block → full default command
44
+ out="$(cd "$REPO" && sh "$JARVIS" --dry-run 2>/dev/null)"; rc=$?
45
+ want="caffeinate -s claude remote-control --name jarvis-proj --spawn worktree --capacity 4"
46
+ if [ "$rc" = 0 ] && [ "$out" = "$want" ]; then
47
+ ok "default derivation: no config → jarvis-proj, capacity 4"
48
+ else
49
+ bad "default derivation" "rc=$rc out=$out"
50
+ fi
51
+
52
+ # 2. caffeinate -s present (operator ruling 6 — asserted on its own so a future
53
+ # edit dropping the wrap fails a NAMED case, not just the exact-match above)
54
+ case "$out" in
55
+ "caffeinate -s "*) ok "caffeinate -s wraps the resolved command (ruling 6 / probe iii)" ;;
56
+ *) bad "caffeinate -s wrap" "out=$out" ;;
57
+ esac
58
+
59
+ # 3. config override — jarvis: block with name_suffix + capacity
60
+ cat > "$REPO/.forge/project.yml" <<'EOF'
61
+ project:
62
+ name: "proj"
63
+ jarvis:
64
+ enabled: true
65
+ name_suffix: "alpha"
66
+ capacity: 2
67
+ EOF
68
+ out="$(cd "$REPO" && sh "$JARVIS" --dry-run 2>/dev/null)"; rc=$?
69
+ want="caffeinate -s claude remote-control --name jarvis-proj-alpha --spawn worktree --capacity 2"
70
+ if [ "$rc" = 0 ] && [ "$out" = "$want" ]; then
71
+ ok "config override: name_suffix + capacity from jarvis: block"
72
+ else
73
+ bad "config override" "rc=$rc out=$out"
74
+ fi
75
+
76
+ # 4. per-machine env seam — FORGE_JARVIS_NAME_SUFFIX beats jarvis.name_suffix
77
+ out="$(cd "$REPO" && FORGE_JARVIS_NAME_SUFFIX=work sh "$JARVIS" --dry-run 2>/dev/null)"; rc=$?
78
+ case "$out" in
79
+ *"--name jarvis-proj-work "*) ok "env FORGE_JARVIS_NAME_SUFFIX overrides config suffix (per-machine seam)" ;;
80
+ *) bad "env suffix override" "rc=$rc out=$out" ;;
81
+ esac
82
+
83
+ # 5. capacity flag override — --capacity beats jarvis.capacity
84
+ out="$(cd "$REPO" && sh "$JARVIS" --dry-run --capacity 7 2>/dev/null)"; rc=$?
85
+ case "$out" in
86
+ *"--capacity 7") ok "--capacity flag overrides config capacity" ;;
87
+ *) bad "capacity flag override" "rc=$rc out=$out" ;;
88
+ esac
89
+
90
+ # 6. no token export — the resolved command never carries an auth env assignment
91
+ # (probe iv: keychain authenticates; a token in the launch line would be the
92
+ # exact regression the B1 bake-in forbids)
93
+ case "$out" in
94
+ *CLAUDE_CODE_OAUTH_TOKEN*|*ANTHROPIC_API_KEY*) bad "no token in resolved command" "out=$out" ;;
95
+ *) ok "no token export in the resolved command (probe iv)" ;;
96
+ esac
97
+
98
+ # 7. NEG: enabled: false → clean refusal (non-zero, no command on stdout)
99
+ cat > "$REPO/.forge/project.yml" <<'EOF'
100
+ jarvis:
101
+ enabled: false
102
+ EOF
103
+ out="$(cd "$REPO" && sh "$JARVIS" --dry-run 2>/dev/null)"; rc=$?
104
+ if [ "$rc" != 0 ] && [ -z "$out" ]; then
105
+ ok "neg-control: jarvis.enabled false → refusal, no command emitted"
106
+ else
107
+ bad "neg-control enabled:false" "rc=$rc out=$out"
108
+ fi
109
+
110
+ # 8. NEG: not a git repo → clean refusal (RC --spawn worktree needs one)
111
+ NOREPO="$ROOT/norepo"
112
+ mkdir -p "$NOREPO"
113
+ out="$(cd "$NOREPO" && sh "$JARVIS" --dry-run 2>/dev/null)"; rc=$?
114
+ if [ "$rc" != 0 ] && [ -z "$out" ]; then
115
+ ok "neg-control: outside a git repo → refusal, no command emitted"
116
+ else
117
+ bad "neg-control non-repo" "rc=$rc out=$out"
118
+ fi
119
+
120
+ # --- summary -----------------------------------------------------------------
121
+ printf '\n%s: %d passed, %d failed\n' "$(basename "$0")" "$PASSED" "$FAILED"
122
+ [ "$FAILED" = 0 ]
@@ -138,6 +138,17 @@ models:
138
138
  # backlog: true # lane is PROJECT-LOCAL config composing these; the framework carries none.
139
139
  # deferred: true # status / backlog (explicit-intake, M21) / deferred view.
140
140
 
141
+ # jarvis: # OPTIONAL front door (Brief-R2 step 4) — the repo's standing presence: a
142
+ # # named `claude remote-control` server whose pre-created session is Jarvis,
143
+ # # started by the operator via .forge/checks/forge-jarvis.sh. Unlike board:,
144
+ # # absence does NOT mean inert — the launcher is operator-invoked, never
145
+ # # ambient, and works with no block (defaults below). See docs/jarvis.md.
146
+ # enabled: true # explicit false = the launcher refuses (the door is switched off)
147
+ # name_suffix: "" # appended to the sticky name jarvis-<repo-basename>; on multi-machine
148
+ # # repos each machine overrides via env FORGE_JARVIS_NAME_SUFFIX so two
149
+ # # live presences never share one name
150
+ # capacity: 4 # RC server session capacity (--capacity), default 4
151
+
141
152
  risks: # What could go wrong?
142
153
  - risk: ""
143
154
  mitigation: ""