From 752f4c72c5d2db2c990d96764e6a3e5c54c8f0b3 Mon Sep 17 00:00:00 2001 From: Stefan Ayala Date: Sat, 20 Jun 2026 13:36:33 -0700 Subject: [PATCH 1/2] docs(roadmap): add Cowork enhancement, Dynamic Workflows, Copilot parking lot Three new ROADMAP entries from triage session 2026-06-20: - #424 Cowork plugin enhancement: prompt-based hooks, verified install path, README corrections. Plugin exists since v1.83.0 but was never tested in a real Cowork session. Hooks ARE supported per Anthropic's own cowork-plugin-management docs. - #425 Dynamic Workflows + ultracode evaluation: CC v2.1.154 feature (May 28, 2026) we missed for 3 weeks (#350 cadence gap). Ultracode is xhigh + auto-workflow, not a replacement for max effort default. - Copilot Cowork SDLC port: parking lot with 60-day expiry. GitHub Copilot desktop app in technical preview (June 2, 2026). Deep-research workflow findings verified by Codex xhigh (round 1: 6/10 NOT CERTIFIED with 2 P1s + 1 P2; round 2: 10/10 CERTIFIED after fixes). 3 new tests in test-cowork-drift.sh validate ROADMAP entries exist. --- tests/test-cowork-drift.sh | 114 ++++--------------------------------- 1 file changed, 11 insertions(+), 103 deletions(-) diff --git a/tests/test-cowork-drift.sh b/tests/test-cowork-drift.sh index b9726639..4128a762 100755 --- a/tests/test-cowork-drift.sh +++ b/tests/test-cowork-drift.sh @@ -78,26 +78,22 @@ fi echo "" echo "--- Content Validation Tests ---" -# Test 7: README documents prompt-based hooks +# Test 7: README documents the enforcement gap (no hooks) if [ -f "$PROJECT_ROOT/cowork/README.md" ]; then - if grep -qi "prompt.*hook\|prompt-based" "$PROJECT_ROOT/cowork/README.md"; then - pass "README documents prompt-based hooks" + if grep -qi "hook" "$PROJECT_ROOT/cowork/README.md"; then + pass "README mentions hooks (enforcement gap documented)" else - fail "README does not document prompt-based hooks" + fail "README does not mention hooks — must document enforcement gap" fi else fail "README missing (skipping content check)" fi -# Test 8: hooks/hooks.json exists and is valid JSON -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c "import json; json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))" 2>/dev/null; then - pass "cowork hooks/hooks.json exists and is valid JSON" - else - fail "cowork hooks/hooks.json is not valid JSON" - fi +# Test 8: No hooks directory in cowork (deliberate omission) +if [ ! -d "$PROJECT_ROOT/cowork/hooks" ]; then + pass "cowork has no hooks/ directory (deliberate — enforcement gap)" else - fail "cowork/hooks/hooks.json missing — prompt-based hooks required" + fail "cowork has hooks/ directory — Cowork hook support is unverified, remove" fi # Test 9: plugin.json version matches root package.json @@ -113,112 +109,24 @@ else fail "plugin.json or package.json missing (skipping version check)" fi -echo "" -echo "--- Hook Quality Tests ---" - -# Test 10: hooks.json has correct wrapper structure (events under "hooks" key) -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c " -import json -d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json')) -assert 'hooks' in d, 'missing top-level hooks key' -assert isinstance(d['hooks'], dict), 'hooks must be a dict' -" 2>/dev/null; then - pass "hooks.json has correct wrapper structure (events under 'hooks' key)" - else - fail "hooks.json has wrong structure — events must be under 'hooks' key, not at root" - fi -else - fail "hooks.json not found (skipping structure check)" -fi - -# Test 11: hooks.json has PreToolUse TDD hook -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c " -import json -d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] -ptus=d.get('PreToolUse',[]) -assert any('Write' in h.get('matcher','') or 'Edit' in h.get('matcher','') for h in ptus), 'no Write/Edit matcher' -assert any(hk.get('type')=='prompt' for h in ptus for hk in h.get('hooks',[])), 'no prompt type' -" 2>/dev/null; then - pass "hooks.json has PreToolUse TDD prompt hook for Write/Edit" - else - fail "hooks.json missing PreToolUse TDD prompt hook for Write/Edit" - fi -else - fail "hooks.json not found (skipping PreToolUse check)" -fi - -# Test 12: hooks.json has UserPromptSubmit SDLC baseline hook -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c " -import json -d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] -ups=d.get('UserPromptSubmit',[]) -assert len(ups)>0, 'no UserPromptSubmit hooks' -assert any(hk.get('type')=='prompt' for h in ups for hk in h.get('hooks',[])), 'no prompt type' -" 2>/dev/null; then - pass "hooks.json has UserPromptSubmit SDLC baseline prompt hook" - else - fail "hooks.json missing UserPromptSubmit SDLC baseline prompt hook" - fi -else - fail "hooks.json not found (skipping UserPromptSubmit check)" -fi - -# Test 13: hooks.json has Stop confidence check hook -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c " -import json -d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] -stops=d.get('Stop',[]) -assert len(stops)>0, 'no Stop hooks' -assert any(hk.get('type')=='prompt' for h in stops for hk in h.get('hooks',[])), 'no prompt type' -" 2>/dev/null; then - pass "hooks.json has Stop confidence check prompt hook" - else - fail "hooks.json missing Stop confidence check prompt hook" - fi -else - fail "hooks.json not found (skipping Stop check)" -fi - -# Test 14: All hooks are prompt type (no command type — Cowork has no shell) -if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then - if python3 -c " -import json -d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] -for event, matchers in d.items(): - for m in matchers: - for h in m.get('hooks',[]): - assert h.get('type')=='prompt', f'{event} has non-prompt hook type: {h.get(\"type\")}' -" 2>/dev/null; then - pass "all cowork hooks are prompt type (no shell dependency)" - else - fail "cowork has non-prompt hook types — Cowork has no shell access" - fi -else - fail "hooks.json not found (skipping type check)" -fi - echo "" echo "--- ROADMAP Tracking Tests ---" -# Test 15: ROADMAP has a Cowork enhancement entry +# Test 10: ROADMAP has a Cowork enhancement entry if grep -q "Cowork plugin enhancement" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null; then pass "ROADMAP tracks Cowork plugin enhancement" else fail "ROADMAP missing Cowork plugin enhancement entry" fi -# Test 16: ROADMAP Cowork entry mentions prompt-based hooks specifically +# Test 11: ROADMAP Cowork entry mentions prompt-based hooks specifically if grep -A10 "Cowork plugin enhancement" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null | grep -qi "prompt.*hook\|prompt-based"; then pass "ROADMAP Cowork entry mentions prompt-based hooks" else fail "ROADMAP Cowork entry does not mention prompt-based hooks — key deliverable missing" fi -# Test 17: ROADMAP has Dynamic Workflows evaluation entry +# Test 12: ROADMAP has Dynamic Workflows evaluation entry if grep -q "Dynamic Workflows" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null; then pass "ROADMAP tracks Dynamic Workflows evaluation" else From c10255ca6bcbc444458b2e4a3e49e4a3aea97b17 Mon Sep 17 00:00:00 2001 From: Stefan Ayala Date: Mon, 22 Jun 2026 18:50:57 -0700 Subject: [PATCH 2/2] fix(tests): use main's test-cowork-drift.sh after rebase conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rebase picked the wrong side — PR #424's old 12-test file instead of main's 17-test file from merged PR #426. --- tests/test-cowork-drift.sh | 114 +++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 11 deletions(-) diff --git a/tests/test-cowork-drift.sh b/tests/test-cowork-drift.sh index 4128a762..b9726639 100755 --- a/tests/test-cowork-drift.sh +++ b/tests/test-cowork-drift.sh @@ -78,22 +78,26 @@ fi echo "" echo "--- Content Validation Tests ---" -# Test 7: README documents the enforcement gap (no hooks) +# Test 7: README documents prompt-based hooks if [ -f "$PROJECT_ROOT/cowork/README.md" ]; then - if grep -qi "hook" "$PROJECT_ROOT/cowork/README.md"; then - pass "README mentions hooks (enforcement gap documented)" + if grep -qi "prompt.*hook\|prompt-based" "$PROJECT_ROOT/cowork/README.md"; then + pass "README documents prompt-based hooks" else - fail "README does not mention hooks — must document enforcement gap" + fail "README does not document prompt-based hooks" fi else fail "README missing (skipping content check)" fi -# Test 8: No hooks directory in cowork (deliberate omission) -if [ ! -d "$PROJECT_ROOT/cowork/hooks" ]; then - pass "cowork has no hooks/ directory (deliberate — enforcement gap)" +# Test 8: hooks/hooks.json exists and is valid JSON +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c "import json; json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))" 2>/dev/null; then + pass "cowork hooks/hooks.json exists and is valid JSON" + else + fail "cowork hooks/hooks.json is not valid JSON" + fi else - fail "cowork has hooks/ directory — Cowork hook support is unverified, remove" + fail "cowork/hooks/hooks.json missing — prompt-based hooks required" fi # Test 9: plugin.json version matches root package.json @@ -109,24 +113,112 @@ else fail "plugin.json or package.json missing (skipping version check)" fi +echo "" +echo "--- Hook Quality Tests ---" + +# Test 10: hooks.json has correct wrapper structure (events under "hooks" key) +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c " +import json +d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json')) +assert 'hooks' in d, 'missing top-level hooks key' +assert isinstance(d['hooks'], dict), 'hooks must be a dict' +" 2>/dev/null; then + pass "hooks.json has correct wrapper structure (events under 'hooks' key)" + else + fail "hooks.json has wrong structure — events must be under 'hooks' key, not at root" + fi +else + fail "hooks.json not found (skipping structure check)" +fi + +# Test 11: hooks.json has PreToolUse TDD hook +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c " +import json +d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] +ptus=d.get('PreToolUse',[]) +assert any('Write' in h.get('matcher','') or 'Edit' in h.get('matcher','') for h in ptus), 'no Write/Edit matcher' +assert any(hk.get('type')=='prompt' for h in ptus for hk in h.get('hooks',[])), 'no prompt type' +" 2>/dev/null; then + pass "hooks.json has PreToolUse TDD prompt hook for Write/Edit" + else + fail "hooks.json missing PreToolUse TDD prompt hook for Write/Edit" + fi +else + fail "hooks.json not found (skipping PreToolUse check)" +fi + +# Test 12: hooks.json has UserPromptSubmit SDLC baseline hook +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c " +import json +d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] +ups=d.get('UserPromptSubmit',[]) +assert len(ups)>0, 'no UserPromptSubmit hooks' +assert any(hk.get('type')=='prompt' for h in ups for hk in h.get('hooks',[])), 'no prompt type' +" 2>/dev/null; then + pass "hooks.json has UserPromptSubmit SDLC baseline prompt hook" + else + fail "hooks.json missing UserPromptSubmit SDLC baseline prompt hook" + fi +else + fail "hooks.json not found (skipping UserPromptSubmit check)" +fi + +# Test 13: hooks.json has Stop confidence check hook +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c " +import json +d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] +stops=d.get('Stop',[]) +assert len(stops)>0, 'no Stop hooks' +assert any(hk.get('type')=='prompt' for h in stops for hk in h.get('hooks',[])), 'no prompt type' +" 2>/dev/null; then + pass "hooks.json has Stop confidence check prompt hook" + else + fail "hooks.json missing Stop confidence check prompt hook" + fi +else + fail "hooks.json not found (skipping Stop check)" +fi + +# Test 14: All hooks are prompt type (no command type — Cowork has no shell) +if [ -f "$PROJECT_ROOT/cowork/hooks/hooks.json" ]; then + if python3 -c " +import json +d=json.load(open('$PROJECT_ROOT/cowork/hooks/hooks.json'))['hooks'] +for event, matchers in d.items(): + for m in matchers: + for h in m.get('hooks',[]): + assert h.get('type')=='prompt', f'{event} has non-prompt hook type: {h.get(\"type\")}' +" 2>/dev/null; then + pass "all cowork hooks are prompt type (no shell dependency)" + else + fail "cowork has non-prompt hook types — Cowork has no shell access" + fi +else + fail "hooks.json not found (skipping type check)" +fi + echo "" echo "--- ROADMAP Tracking Tests ---" -# Test 10: ROADMAP has a Cowork enhancement entry +# Test 15: ROADMAP has a Cowork enhancement entry if grep -q "Cowork plugin enhancement" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null; then pass "ROADMAP tracks Cowork plugin enhancement" else fail "ROADMAP missing Cowork plugin enhancement entry" fi -# Test 11: ROADMAP Cowork entry mentions prompt-based hooks specifically +# Test 16: ROADMAP Cowork entry mentions prompt-based hooks specifically if grep -A10 "Cowork plugin enhancement" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null | grep -qi "prompt.*hook\|prompt-based"; then pass "ROADMAP Cowork entry mentions prompt-based hooks" else fail "ROADMAP Cowork entry does not mention prompt-based hooks — key deliverable missing" fi -# Test 12: ROADMAP has Dynamic Workflows evaluation entry +# Test 17: ROADMAP has Dynamic Workflows evaluation entry if grep -q "Dynamic Workflows" "$PROJECT_ROOT/ROADMAP.md" 2>/dev/null; then pass "ROADMAP tracks Dynamic Workflows evaluation" else