@nklisch/pi-agile-workflow 0.15.3
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/.claude-plugin/plugin.json +10 -0
- package/.codex-plugin/plugin.json +28 -0
- package/CHANGELOG.md +591 -0
- package/README.md +107 -0
- package/docs/ARCHITECTURE.md +716 -0
- package/docs/MIGRATION.md +419 -0
- package/docs/PRINCIPLES.md +464 -0
- package/docs/ROADMAP.md +95 -0
- package/docs/SPEC.md +855 -0
- package/docs/VISION.md +106 -0
- package/extensions/agile-workflow.test.ts +419 -0
- package/extensions/agile-workflow.ts +467 -0
- package/hooks/hooks.json +52 -0
- package/hooks/scripts/prompt-context.py +628 -0
- package/hooks/scripts/substrate-maintainer.py +359 -0
- package/hooks/scripts/test_prompt_context.py +757 -0
- package/package.json +30 -0
- package/scripts/install-work-view.sh +165 -0
- package/scripts/tests/agent-metadata.test.sh +75 -0
- package/scripts/tests/bump-version.test.sh +552 -0
- package/scripts/tests/channel-parity.test.sh +117 -0
- package/scripts/tests/convert-content-integrity.test.sh +246 -0
- package/scripts/tests/convert-install-routing.test.sh +159 -0
- package/scripts/tests/install-work-view.test.sh +411 -0
- package/scripts/tests/pi-package-metadata.test.sh +119 -0
- package/scripts/tests/work-board-shim.test.sh +239 -0
- package/scripts/tests/work-view-dist-version.test.sh +105 -0
- package/scripts/work-board.sh +64 -0
- package/scripts/work-view.sh +423 -0
- package/skills/autopilot/SKILL.md +330 -0
- package/skills/autopilot/agents/openai.yaml +6 -0
- package/skills/board/SKILL.md +62 -0
- package/skills/board/agents/openai.yaml +6 -0
- package/skills/bold-refactor/SKILL.md +244 -0
- package/skills/bold-refactor/agents/openai.yaml +6 -0
- package/skills/bug-scan/SKILL.md +378 -0
- package/skills/bug-scan/agents/openai.yaml +6 -0
- package/skills/bug-scan/references/async-promises.md +119 -0
- package/skills/bug-scan/references/concurrency-races.md +148 -0
- package/skills/bug-scan/references/data-layer.md +167 -0
- package/skills/bug-scan/references/error-handling.md +197 -0
- package/skills/bug-scan/references/gate-item-template.md +94 -0
- package/skills/bug-scan/references/language-footguns.md +219 -0
- package/skills/bug-scan/references/parked-item-template.md +103 -0
- package/skills/bug-scan/references/report-template.md +115 -0
- package/skills/bug-scan/references/resource-leaks.md +199 -0
- package/skills/bug-scan/references/state-closures.md +148 -0
- package/skills/bug-scan/references/time-numbers.md +158 -0
- package/skills/convert/SKILL.md +1463 -0
- package/skills/convert/agents/openai.yaml +6 -0
- package/skills/convert/references/legacy-overlap-migration.md +179 -0
- package/skills/deep-code-scan/SKILL.md +378 -0
- package/skills/deep-code-scan/agents/openai.yaml +6 -0
- package/skills/deep-code-scan/references/artifact-ledger.md +148 -0
- package/skills/deep-code-scan/references/consolidation.md +91 -0
- package/skills/deep-code-scan/references/decomposition.md +127 -0
- package/skills/deep-code-scan/references/item-templates.md +263 -0
- package/skills/deep-code-scan/references/lane-catalog.md +129 -0
- package/skills/deep-code-scan/references/review-gauntlet.md +108 -0
- package/skills/deep-code-scan/references/scanner-brief.md +152 -0
- package/skills/e2e-test-design/SKILL.md +517 -0
- package/skills/e2e-test-design/references/anti-tautology.md +261 -0
- package/skills/e2e-test-design/references/service-mocks.md +234 -0
- package/skills/e2e-test-design/references/test-taxonomy.md +211 -0
- package/skills/epic-design/SKILL.md +476 -0
- package/skills/epicize/SKILL.md +210 -0
- package/skills/epicize/agents/openai.yaml +6 -0
- package/skills/feature-design/SKILL.md +472 -0
- package/skills/fix/SKILL.md +173 -0
- package/skills/gate-cruft/SKILL.md +258 -0
- package/skills/gate-docs/SKILL.md +278 -0
- package/skills/gate-patterns/SKILL.md +389 -0
- package/skills/gate-refactor/SKILL.md +408 -0
- package/skills/gate-security/SKILL.md +275 -0
- package/skills/gate-tests/SKILL.md +367 -0
- package/skills/groom/SKILL.md +162 -0
- package/skills/groom/agents/openai.yaml +6 -0
- package/skills/ideate/SKILL.md +185 -0
- package/skills/ideate/agents/openai.yaml +6 -0
- package/skills/implement/SKILL.md +288 -0
- package/skills/implement-orchestrator/SKILL.md +604 -0
- package/skills/park/SKILL.md +111 -0
- package/skills/perf-design/SKILL.md +427 -0
- package/skills/perf-scout/SKILL.md +404 -0
- package/skills/perf-scout/agents/openai.yaml +6 -0
- package/skills/perf-scout/references/algorithmic-and-data-structures.md +126 -0
- package/skills/perf-scout/references/approximation-and-precomputation.md +136 -0
- package/skills/perf-scout/references/caching-and-memoization.md +123 -0
- package/skills/perf-scout/references/compiler-runtime-and-language.md +136 -0
- package/skills/perf-scout/references/database-and-storage-internals.md +144 -0
- package/skills/perf-scout/references/distributed-systems.md +150 -0
- package/skills/perf-scout/references/game-engine-and-realtime.md +136 -0
- package/skills/perf-scout/references/gpu-and-accelerators.md +130 -0
- package/skills/perf-scout/references/idea-ranking.md +75 -0
- package/skills/perf-scout/references/io-and-batching.md +135 -0
- package/skills/perf-scout/references/memory-and-data-locality.md +137 -0
- package/skills/perf-scout/references/parallelism-and-vectorization.md +126 -0
- package/skills/perf-scout/references/parked-item-template.md +117 -0
- package/skills/perf-scout/references/peer-review-pass.md +150 -0
- package/skills/perf-scout/references/report-template.md +148 -0
- package/skills/principles/SKILL.md +678 -0
- package/skills/principles/references/models.md +191 -0
- package/skills/principles/references/subagents.md +158 -0
- package/skills/prose-author/SKILL.md +185 -0
- package/skills/refactor-conventions-creator/SKILL.md +359 -0
- package/skills/refactor-conventions-creator/agents/openai.yaml +6 -0
- package/skills/refactor-conventions-creator/references/common-structures.md +91 -0
- package/skills/refactor-conventions-creator/references/common-styles.md +90 -0
- package/skills/refactor-design/SKILL.md +384 -0
- package/skills/release-deploy/SKILL.md +667 -0
- package/skills/release-deploy/agents/openai.yaml +6 -0
- package/skills/research/SKILL.md +166 -0
- package/skills/research/agents/openai.yaml +6 -0
- package/skills/review/SKILL.md +267 -0
- package/skills/review/references/deep-review.md +98 -0
- package/skills/review/references/review-lenses.md +68 -0
- package/skills/review/references/substrate-side-effects.md +161 -0
- package/skills/review/references/target-resolution.md +52 -0
- package/skills/scope/SKILL.md +486 -0
- package/work-view/Cargo.lock +486 -0
- package/work-view/Cargo.toml +9 -0
- package/work-view/crates/cli/.work-view-version +1 -0
- package/work-view/crates/cli/Cargo.toml +18 -0
- package/work-view/crates/cli/src/actionable.rs +500 -0
- package/work-view/crates/cli/src/args.rs +792 -0
- package/work-view/crates/cli/src/board/assets/board.css +855 -0
- package/work-view/crates/cli/src/board/assets/board.js +259 -0
- package/work-view/crates/cli/src/board/assets/card.js +139 -0
- package/work-view/crates/cli/src/board/assets/components.css +290 -0
- package/work-view/crates/cli/src/board/assets/dependency.js +1193 -0
- package/work-view/crates/cli/src/board/assets/detail.js +256 -0
- package/work-view/crates/cli/src/board/assets/filters.js +389 -0
- package/work-view/crates/cli/src/board/assets/index.html +77 -0
- package/work-view/crates/cli/src/board/assets/kanban.js +231 -0
- package/work-view/crates/cli/src/board/assets/markdown.js +260 -0
- package/work-view/crates/cli/src/board/assets/motion.css +131 -0
- package/work-view/crates/cli/src/board/assets/state.js +245 -0
- package/work-view/crates/cli/src/board/assets/table.js +304 -0
- package/work-view/crates/cli/src/board/assets/tokens.css +602 -0
- package/work-view/crates/cli/src/board/assets/views.js +41 -0
- package/work-view/crates/cli/src/board/assets.rs +162 -0
- package/work-view/crates/cli/src/board/feed.rs +204 -0
- package/work-view/crates/cli/src/board/mod.rs +246 -0
- package/work-view/crates/cli/src/board/open.rs +144 -0
- package/work-view/crates/cli/src/board/server.rs +407 -0
- package/work-view/crates/cli/src/main.rs +195 -0
- package/work-view/crates/cli/src/render.rs +354 -0
- package/work-view/crates/cli/src/scope.rs +157 -0
- package/work-view/crates/cli/src/stale.rs +581 -0
- package/work-view/crates/cli/tests/board-js/dependency-table.test.mjs +64 -0
- package/work-view/crates/cli/tests/board-js/expanded-browsing.test.mjs +79 -0
- package/work-view/crates/cli/tests/board-js/harness-smoke.test.mjs +11 -0
- package/work-view/crates/cli/tests/board-js/harness.mjs +437 -0
- package/work-view/crates/cli/tests/board-js/kanban-detail.test.mjs +75 -0
- package/work-view/crates/cli/tests/board-js/markdown-filter.test.mjs +60 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/CONVENTIONS.md +3 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/epics/epic-alpha.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/features/feat-a.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/features/feat-b.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/stories/story-alpha-1.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/active/stories/story-research-1.md +19 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/archive/feat-done.md +16 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/archive/feat-shipped.md +18 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/backlog/idea-backlog.md +7 -0
- package/work-view/crates/cli/tests/fixtures/golden/.work/releases/v1.0/v1.0.md +16 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/CONVENTIONS.md +6 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-dep-done.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-design-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/features/feat-impl-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/ready-drafting/.work/active/stories/story-review-ready.md +17 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/CONVENTIONS.md +4 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/active/epics/malformed-no-closing-fence.md +8 -0
- package/work-view/crates/cli/tests/fixtures/with-malformed/.work/active/features/good-item.md +16 -0
- package/work-view/crates/cli/tests/integration.rs +2833 -0
- package/work-view/crates/core/Cargo.toml +13 -0
- package/work-view/crates/core/src/error.rs +61 -0
- package/work-view/crates/core/src/filter.rs +804 -0
- package/work-view/crates/core/src/graph.rs +324 -0
- package/work-view/crates/core/src/index.rs +590 -0
- package/work-view/crates/core/src/lib.rs +54 -0
- package/work-view/crates/core/src/model.rs +202 -0
- package/work-view/crates/core/src/parse.rs +494 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/CONVENTIONS.md +15 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/epics/epic-core.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/features/feat-parser.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/features/feat-query.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/malformed-no-id.md +15 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/story-parse-unit.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/active/stories/story-security-gate.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/archive/feat-old.md +16 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/archive/feat-parser.md +17 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/backlog/idea-future-board.md +7 -0
- package/work-view/crates/core/tests/fixtures/golden/.work/releases/v1.0/v1.0.md +16 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/CONVENTIONS.md +10 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/archive/dup-item.md +18 -0
- package/work-view/crates/core/tests/fixtures/precedence/.work/releases/v2.0/dup-item.md +18 -0
- package/work-view/crates/core/tests/integration.rs +541 -0
- package/work-view/dist/.gitattributes +1 -0
- package/work-view/dist/README.md +42 -0
- package/work-view/dist/aarch64-apple-darwin/work-view +0 -0
- package/work-view/dist/aarch64-unknown-linux-musl/work-view +0 -0
- package/work-view/dist/x86_64-apple-darwin/work-view +0 -0
- package/work-view/dist/x86_64-unknown-linux-musl/work-view +0 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# work-board-shim.test.sh — routing tests for scripts/work-board.sh.
|
|
3
|
+
#
|
|
4
|
+
# work-board.sh is a decision shim with three routing branches:
|
|
5
|
+
# 1. No `.work/CONVENTIONS.md` in CWD or any ancestor -> exit 2 (no substrate)
|
|
6
|
+
# 2. `.work/bin/work-view` missing or not executable -> exit 1 (compiled
|
|
7
|
+
# work-view binary required)
|
|
8
|
+
# 3. work-view present but FAILS `board --help` -> exit 1, does NOT
|
|
9
|
+
# exec the board
|
|
10
|
+
# 4. work-view present and PASSES `board --help` -> exec'd as
|
|
11
|
+
# `work-view board "$@"`
|
|
12
|
+
#
|
|
13
|
+
# Self-contained: builds temp substrate roots and stub `work-view` binaries,
|
|
14
|
+
# following the harness pattern from install-work-view.test.sh. Runnable locally
|
|
15
|
+
# and from CI. Exits non-zero if any assertion fails.
|
|
16
|
+
|
|
17
|
+
set -uo pipefail
|
|
18
|
+
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
SHIM="${SCRIPT_DIR}/../work-board.sh"
|
|
21
|
+
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
# Counters
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
PASS=0
|
|
26
|
+
FAIL=0
|
|
27
|
+
ERRORS=()
|
|
28
|
+
|
|
29
|
+
assert_eq() {
|
|
30
|
+
local label="$1" expected="$2" actual="$3"
|
|
31
|
+
if [ "$expected" = "$actual" ]; then
|
|
32
|
+
echo " PASS: $label"
|
|
33
|
+
((PASS++))
|
|
34
|
+
else
|
|
35
|
+
echo " FAIL: $label"
|
|
36
|
+
echo " expected: $(printf '%q' "$expected")"
|
|
37
|
+
echo " actual: $(printf '%q' "$actual")"
|
|
38
|
+
((FAIL++))
|
|
39
|
+
ERRORS+=("$label")
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
assert_true() {
|
|
44
|
+
local label="$1"
|
|
45
|
+
if eval "$2"; then
|
|
46
|
+
echo " PASS: $label"
|
|
47
|
+
((PASS++))
|
|
48
|
+
else
|
|
49
|
+
echo " FAIL: $label"
|
|
50
|
+
echo " condition false: $2"
|
|
51
|
+
((FAIL++))
|
|
52
|
+
ERRORS+=("$label")
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
assert_false() {
|
|
57
|
+
local label="$1"
|
|
58
|
+
if ! eval "$2"; then
|
|
59
|
+
echo " PASS: $label"
|
|
60
|
+
((PASS++))
|
|
61
|
+
else
|
|
62
|
+
echo " FAIL: $label"
|
|
63
|
+
echo " expected false but was true: $2"
|
|
64
|
+
((FAIL++))
|
|
65
|
+
ERRORS+=("$label")
|
|
66
|
+
fi
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Preflight
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Preflight: work-board.sh present ==="
|
|
74
|
+
assert_true "work-board.sh exists" "[ -f '$SHIM' ]"
|
|
75
|
+
if [ ! -f "$SHIM" ]; then
|
|
76
|
+
echo "ERROR: cannot locate work-board.sh at $SHIM" >&2
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
# new_substrate <with-conventions?> — temp dir; if first arg is "yes", seeds
|
|
82
|
+
# .work/CONVENTIONS.md so it reads as a substrate root.
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
new_substrate() {
|
|
85
|
+
local with_conv="${1:-yes}"
|
|
86
|
+
local root
|
|
87
|
+
root="$(mktemp -d)"
|
|
88
|
+
mkdir -p "${root}/.work"
|
|
89
|
+
if [ "$with_conv" = "yes" ]; then
|
|
90
|
+
printf '# Conventions\n' > "${root}/.work/CONVENTIONS.md"
|
|
91
|
+
fi
|
|
92
|
+
printf '%s' "$root"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# write_work_view <root> <board-help-rc> <arglog-path>
|
|
96
|
+
# Installs an executable .work/bin/work-view stub that:
|
|
97
|
+
# * exits <board-help-rc> for `board --help`
|
|
98
|
+
# * for any other `board ...` invocation, appends "$@" to <arglog-path> and
|
|
99
|
+
# exits 0 (lets us prove it was exec'd with `board "$@"`).
|
|
100
|
+
write_work_view() {
|
|
101
|
+
local root="$1" help_rc="$2" arglog="$3"
|
|
102
|
+
local bin="${root}/.work/bin/work-view"
|
|
103
|
+
mkdir -p "${root}/.work/bin"
|
|
104
|
+
cat > "$bin" <<EOF
|
|
105
|
+
#!/usr/bin/env bash
|
|
106
|
+
if [[ "\${1:-}" == "board" && "\${2:-}" == "--help" ]]; then
|
|
107
|
+
exit ${help_rc}
|
|
108
|
+
fi
|
|
109
|
+
if [[ "\${1:-}" == "board" ]]; then
|
|
110
|
+
shift
|
|
111
|
+
printf 'board %s\n' "\$*" >> "${arglog}"
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
exit 0
|
|
115
|
+
EOF
|
|
116
|
+
chmod +x "$bin"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# run_board <root> [args...] — invoke the shim from inside <root>.
|
|
120
|
+
# Captures stdout in $BOARD_OUT, stderr file in $BOARD_ERR, rc in $BOARD_RC.
|
|
121
|
+
run_board() {
|
|
122
|
+
local root="$1"; shift
|
|
123
|
+
BOARD_ERR="${root}/.board.err"
|
|
124
|
+
BOARD_OUT=$(
|
|
125
|
+
cd "$root" &&
|
|
126
|
+
bash "$SHIM" "$@" 2>"$BOARD_ERR"
|
|
127
|
+
)
|
|
128
|
+
BOARD_RC=$?
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
# Test group 1: no substrate ancestor -> exit 2, stderr mentions no substrate
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
echo ""
|
|
135
|
+
echo "=== Test group 1: no .work/CONVENTIONS.md ancestor -> exit 2 ==="
|
|
136
|
+
|
|
137
|
+
# A directory with NO .work/CONVENTIONS.md anywhere up to root. mktemp -d lands
|
|
138
|
+
# under TMPDIR; we additionally guard by removing any .work it might inherit.
|
|
139
|
+
NOSUB="$(mktemp -d)"
|
|
140
|
+
run_board "$NOSUB"
|
|
141
|
+
assert_eq "no-substrate exits 2" "2" "$BOARD_RC"
|
|
142
|
+
assert_true "no-substrate stderr mentions no substrate" \
|
|
143
|
+
"grep -qi 'no substrate' '$BOARD_ERR'"
|
|
144
|
+
rm -rf "$NOSUB"
|
|
145
|
+
|
|
146
|
+
# ---------------------------------------------------------------------------
|
|
147
|
+
# Test group 2: substrate present but work-view missing -> exit 1
|
|
148
|
+
# ---------------------------------------------------------------------------
|
|
149
|
+
echo ""
|
|
150
|
+
echo "=== Test group 2: missing/non-exec work-view -> exit 1 ==="
|
|
151
|
+
|
|
152
|
+
ROOT_MISSING="$(new_substrate yes)"
|
|
153
|
+
run_board "$ROOT_MISSING"
|
|
154
|
+
assert_eq "missing work-view exits 1" "1" "$BOARD_RC"
|
|
155
|
+
assert_true "missing work-view message names the compiled work-view binary" \
|
|
156
|
+
"grep -qi 'compiled work-view binary' '$BOARD_ERR'"
|
|
157
|
+
rm -rf "$ROOT_MISSING"
|
|
158
|
+
|
|
159
|
+
# Present but NOT executable (file exists, mode 0644) -> still exit 1.
|
|
160
|
+
ROOT_NOEXEC="$(new_substrate yes)"
|
|
161
|
+
mkdir -p "${ROOT_NOEXEC}/.work/bin"
|
|
162
|
+
printf '#!/usr/bin/env bash\nexit 0\n' > "${ROOT_NOEXEC}/.work/bin/work-view"
|
|
163
|
+
chmod 0644 "${ROOT_NOEXEC}/.work/bin/work-view"
|
|
164
|
+
run_board "$ROOT_NOEXEC"
|
|
165
|
+
assert_eq "non-executable work-view exits 1" "1" "$BOARD_RC"
|
|
166
|
+
assert_true "non-executable work-view message names the compiled work-view binary" \
|
|
167
|
+
"grep -qi 'compiled work-view binary' '$BOARD_ERR'"
|
|
168
|
+
rm -rf "$ROOT_NOEXEC"
|
|
169
|
+
|
|
170
|
+
# ---------------------------------------------------------------------------
|
|
171
|
+
# Test group 3: work-view fails `board --help` -> exit 1, does NOT exec board
|
|
172
|
+
# ---------------------------------------------------------------------------
|
|
173
|
+
echo ""
|
|
174
|
+
echo "=== Test group 3: work-view fails 'board --help' -> exit 1, no exec ==="
|
|
175
|
+
|
|
176
|
+
ROOT_FAIL="$(new_substrate yes)"
|
|
177
|
+
ARGLOG_FAIL="${ROOT_FAIL}/.board-args.log"
|
|
178
|
+
write_work_view "$ROOT_FAIL" 1 "$ARGLOG_FAIL"
|
|
179
|
+
run_board "$ROOT_FAIL" --port 9999
|
|
180
|
+
assert_eq "board-incapable work-view exits 1" "1" "$BOARD_RC"
|
|
181
|
+
assert_true "board-incapable message says board unsupported / refresh" \
|
|
182
|
+
"grep -qiE 'does not support the interactive board|refresh' '$BOARD_ERR'"
|
|
183
|
+
assert_false "board-incapable did NOT exec board (no arglog written)" \
|
|
184
|
+
"[ -f '$ARGLOG_FAIL' ]"
|
|
185
|
+
rm -rf "$ROOT_FAIL"
|
|
186
|
+
|
|
187
|
+
# ---------------------------------------------------------------------------
|
|
188
|
+
# Test group 4: work-view passes `board --help` -> exec'd as board "$@"
|
|
189
|
+
# ---------------------------------------------------------------------------
|
|
190
|
+
echo ""
|
|
191
|
+
echo "=== Test group 4: board-capable work-view -> exec board \"\$@\" ==="
|
|
192
|
+
|
|
193
|
+
ROOT_OK="$(new_substrate yes)"
|
|
194
|
+
ARGLOG_OK="${ROOT_OK}/.board-args.log"
|
|
195
|
+
write_work_view "$ROOT_OK" 0 "$ARGLOG_OK"
|
|
196
|
+
run_board "$ROOT_OK" --port 8181 --no-open
|
|
197
|
+
assert_eq "board-capable work-view exits 0" "0" "$BOARD_RC"
|
|
198
|
+
assert_true "board-capable exec'd board with forwarded args" \
|
|
199
|
+
"[ -f '$ARGLOG_OK' ] && grep -qx 'board --port 8181 --no-open' '$ARGLOG_OK'"
|
|
200
|
+
rm -rf "$ROOT_OK"
|
|
201
|
+
|
|
202
|
+
# Board-capable with NO extra args -> exec'd as `board` (empty arg tail).
|
|
203
|
+
ROOT_OK2="$(new_substrate yes)"
|
|
204
|
+
ARGLOG_OK2="${ROOT_OK2}/.board-args.log"
|
|
205
|
+
write_work_view "$ROOT_OK2" 0 "$ARGLOG_OK2"
|
|
206
|
+
run_board "$ROOT_OK2"
|
|
207
|
+
assert_eq "board-capable (no args) exits 0" "0" "$BOARD_RC"
|
|
208
|
+
assert_true "board-capable (no args) exec'd plain board" \
|
|
209
|
+
"[ -f '$ARGLOG_OK2' ] && grep -qx 'board ' '$ARGLOG_OK2'"
|
|
210
|
+
rm -rf "$ROOT_OK2"
|
|
211
|
+
|
|
212
|
+
# ---------------------------------------------------------------------------
|
|
213
|
+
# Test group 5: --help short-circuits before any substrate/binary check
|
|
214
|
+
# ---------------------------------------------------------------------------
|
|
215
|
+
echo ""
|
|
216
|
+
echo "=== Test group 5: --help prints usage, exit 0, no substrate needed ==="
|
|
217
|
+
|
|
218
|
+
NOSUB_HELP="$(mktemp -d)"
|
|
219
|
+
run_board "$NOSUB_HELP" --help
|
|
220
|
+
assert_eq "--help exits 0 even with no substrate" "0" "$BOARD_RC"
|
|
221
|
+
assert_true "--help prints usage" \
|
|
222
|
+
"printf '%s' \"\$BOARD_OUT\" | grep -qi 'launch the agile-workflow live substrate board'"
|
|
223
|
+
rm -rf "$NOSUB_HELP"
|
|
224
|
+
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
# Summary
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
echo ""
|
|
229
|
+
echo "============================================================"
|
|
230
|
+
echo "Results: ${PASS} passed, ${FAIL} failed"
|
|
231
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
232
|
+
echo "Failed tests:"
|
|
233
|
+
for e in "${ERRORS[@]}"; do
|
|
234
|
+
echo " - $e"
|
|
235
|
+
done
|
|
236
|
+
fi
|
|
237
|
+
echo "============================================================"
|
|
238
|
+
|
|
239
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# work-view-dist-version.test.sh — guard committed prebuilt version stamps.
|
|
3
|
+
#
|
|
4
|
+
# The installer trusts supported-platform prebuilts only after their --version
|
|
5
|
+
# matches the plugin manifest. This test keeps the committed dist/ tree in that
|
|
6
|
+
# same state so a version bump cannot publish stale board-capable binaries.
|
|
7
|
+
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
12
|
+
PLUGIN_JSON="${PLUGIN_ROOT}/.claude-plugin/plugin.json"
|
|
13
|
+
|
|
14
|
+
PASS=0
|
|
15
|
+
FAIL=0
|
|
16
|
+
ERRORS=()
|
|
17
|
+
|
|
18
|
+
assert_true() {
|
|
19
|
+
local label="$1"
|
|
20
|
+
if eval "$2"; then
|
|
21
|
+
echo " PASS: $label"
|
|
22
|
+
((PASS++))
|
|
23
|
+
else
|
|
24
|
+
echo " FAIL: $label"
|
|
25
|
+
echo " condition false: $2"
|
|
26
|
+
((FAIL++))
|
|
27
|
+
ERRORS+=("$label")
|
|
28
|
+
fi
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
assert_eq() {
|
|
32
|
+
local label="$1" expected="$2" actual="$3"
|
|
33
|
+
if [ "$expected" = "$actual" ]; then
|
|
34
|
+
echo " PASS: $label"
|
|
35
|
+
((PASS++))
|
|
36
|
+
else
|
|
37
|
+
echo " FAIL: $label"
|
|
38
|
+
echo " expected: $(printf '%q' "$expected")"
|
|
39
|
+
echo " actual: $(printf '%q' "$actual")"
|
|
40
|
+
((FAIL++))
|
|
41
|
+
ERRORS+=("$label")
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
plugin_version() {
|
|
46
|
+
sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$PLUGIN_JSON" | head -n 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
echo ""
|
|
50
|
+
echo "=== Preflight: plugin manifest and dist binaries ==="
|
|
51
|
+
assert_true "plugin manifest exists" "[ -f '$PLUGIN_JSON' ]"
|
|
52
|
+
VERSION="$(plugin_version)"
|
|
53
|
+
assert_true "plugin version is readable" "[ -n '$VERSION' ]"
|
|
54
|
+
|
|
55
|
+
TRIPLES=(
|
|
56
|
+
x86_64-unknown-linux-musl
|
|
57
|
+
aarch64-unknown-linux-musl
|
|
58
|
+
x86_64-apple-darwin
|
|
59
|
+
aarch64-apple-darwin
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
echo ""
|
|
63
|
+
echo "=== Test group 1: all supported prebuilts embed plugin version ==="
|
|
64
|
+
for triple in "${TRIPLES[@]}"; do
|
|
65
|
+
bin="${PLUGIN_ROOT}/work-view/dist/${triple}/work-view"
|
|
66
|
+
assert_true "${triple} binary exists" "[ -f '$bin' ]"
|
|
67
|
+
assert_true "${triple} binary executable" "[ -x '$bin' ]"
|
|
68
|
+
assert_true "${triple} embeds work-view ${VERSION}" \
|
|
69
|
+
"LC_ALL=C grep -a -q 'work-view ${VERSION}\\|${VERSION}' '$bin'"
|
|
70
|
+
done
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Test group 2: native Linux x86_64 binary reports version and board help ==="
|
|
74
|
+
HOST_S="$(uname -s 2>/dev/null || printf unknown)"
|
|
75
|
+
HOST_M="$(uname -m 2>/dev/null || printf unknown)"
|
|
76
|
+
if [ "$HOST_S" = "Linux" ] && { [ "$HOST_M" = "x86_64" ] || [ "$HOST_M" = "amd64" ]; }; then
|
|
77
|
+
native="${PLUGIN_ROOT}/work-view/dist/x86_64-unknown-linux-musl/work-view"
|
|
78
|
+
assert_eq "native --version matches plugin" "work-view ${VERSION}" "$("$native" --version)"
|
|
79
|
+
assert_true "native supports board --help" "'$native' board --help >/dev/null 2>&1"
|
|
80
|
+
else
|
|
81
|
+
echo " SKIP: native execution check requires Linux x86_64 host (got ${HOST_S}/${HOST_M})"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
echo ""
|
|
85
|
+
echo "=== Test group 3: repo dogfood work-view install matches plugin ==="
|
|
86
|
+
DOGFOOD_BIN="${PLUGIN_ROOT}/../../.work/bin/work-view"
|
|
87
|
+
if [ -e "$DOGFOOD_BIN" ]; then
|
|
88
|
+
assert_true "dogfood work-view executable" "[ -x '$DOGFOOD_BIN' ]"
|
|
89
|
+
assert_eq "dogfood --version matches plugin" "work-view ${VERSION}" "$("$DOGFOOD_BIN" --version)"
|
|
90
|
+
else
|
|
91
|
+
echo " SKIP: no repo dogfood .work/bin/work-view install present"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
echo ""
|
|
95
|
+
echo "============================================================"
|
|
96
|
+
echo "Results: ${PASS} passed, ${FAIL} failed"
|
|
97
|
+
if [ ${#ERRORS[@]} -gt 0 ]; then
|
|
98
|
+
echo "Failed tests:"
|
|
99
|
+
for e in "${ERRORS[@]}"; do
|
|
100
|
+
echo " - $e"
|
|
101
|
+
done
|
|
102
|
+
fi
|
|
103
|
+
echo "============================================================"
|
|
104
|
+
|
|
105
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Compatibility shim for the live substrate board.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
usage() {
|
|
7
|
+
cat <<'USAGE'
|
|
8
|
+
work-board - launch the agile-workflow live substrate board
|
|
9
|
+
|
|
10
|
+
Usage: work-board [OPTIONS]
|
|
11
|
+
|
|
12
|
+
Options are forwarded to:
|
|
13
|
+
.work/bin/work-view board [OPTIONS]
|
|
14
|
+
|
|
15
|
+
Common options:
|
|
16
|
+
--port <n> Port to bind on localhost (default: 8181)
|
|
17
|
+
--no-open Print the URL without opening a browser
|
|
18
|
+
--print Alias for --no-open
|
|
19
|
+
--help, -h Show this help
|
|
20
|
+
|
|
21
|
+
The interactive board requires a compiled board-capable work-view binary.
|
|
22
|
+
USAGE
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
find_substrate_root() {
|
|
26
|
+
local dir
|
|
27
|
+
dir="$(pwd)"
|
|
28
|
+
while [[ "$dir" != "/" && -n "$dir" ]]; do
|
|
29
|
+
if [[ -f "$dir/.work/CONVENTIONS.md" ]]; then
|
|
30
|
+
printf '%s\n' "$dir"
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
dir="$(dirname "$dir")"
|
|
34
|
+
done
|
|
35
|
+
return 1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
case "${1:-}" in
|
|
39
|
+
--help|-h)
|
|
40
|
+
usage
|
|
41
|
+
exit 0
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
44
|
+
|
|
45
|
+
ROOT="$(find_substrate_root || true)"
|
|
46
|
+
if [[ -z "$ROOT" ]]; then
|
|
47
|
+
echo "work-board: no substrate found (no .work/CONVENTIONS.md in CWD or ancestor)" >&2
|
|
48
|
+
exit 2
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
WORK_VIEW="$ROOT/.work/bin/work-view"
|
|
52
|
+
if [[ ! -x "$WORK_VIEW" ]]; then
|
|
53
|
+
echo "work-board: interactive board requires a compiled work-view binary at $WORK_VIEW" >&2
|
|
54
|
+
echo "work-board: refresh agile-workflow's work-view binary, then run .work/bin/work-view board" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
if "$WORK_VIEW" board --help >/dev/null 2>&1; then
|
|
59
|
+
exec "$WORK_VIEW" board "$@"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
echo "work-board: installed work-view does not support the interactive board" >&2
|
|
63
|
+
echo "work-board: refresh agile-workflow's compiled work-view binary, then run .work/bin/work-view board" >&2
|
|
64
|
+
exit 1
|