Skip to content

Commit d8f7608

Browse files
withkynamclaude
andcommitted
Release v2.2.0
README viral enhancement: - Card-style HTML tables (2-col max, mobile-friendly) - Tool logo badges (shields.io) and tech stack logos (skillicons.dev) - Competitive positioning vs Superpowers/GSD/gstack - Market stats, persona cards, "At a Glance" grid - Tanjiro "Spec Breathing" parody quote - Section reorder: Problem/Fix first - Karpathy and Garry Tan centered quotes All 5 translations updated (zh-CN, ja-JP, ko-KR, vi-VN, pt-BR): - Full structural parity with English README - Translated Tanjiro quote with locale anime terminology - Fixed logo paths for docs/i18n/ relative location Harness improvements: - New: intent-clarification protocol - New: parallel fan-out checkpoint protocol - Hardened phase-program loop (regression checks, commit checkpoints) - Inline fan-out signals in all 4 CLAUDE.md phase transitions - vc-publish: added mandatory resolver-diff rule - Hook test suite (18 new test files) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8fd160f commit d8f7608

33 files changed

Lines changed: 10191 additions & 1686 deletions
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env node
2+
'use strict';
3+
4+
const { handleSessionStateEvent } = require('../session-state.cjs');
5+
6+
function assert(condition, message) {
7+
if (!condition) throw new Error(message);
8+
}
9+
10+
async function runCase(name, fn) {
11+
try {
12+
await fn();
13+
console.log(`✓ ${name}`);
14+
return true;
15+
} catch (error) {
16+
console.log(`✗ ${name}`);
17+
console.log(` Error: ${error.message}`);
18+
return false;
19+
}
20+
}
21+
22+
async function run() {
23+
const results = [];
24+
25+
results.push(await runCase('skips cleanly when hook disabled', async () => {
26+
const result = await handleSessionStateEvent(
27+
{ hook_event_name: 'PostToolUse', session_id: 'abc' },
28+
{ enabled: false }
29+
);
30+
assert(result.action === 'skipped-disabled', 'expected disabled skip');
31+
}));
32+
33+
results.push(await runCase('skips when session id missing', async () => {
34+
const result = await handleSessionStateEvent(
35+
{ hook_event_name: 'PostToolUse' },
36+
{ enabled: true }
37+
);
38+
assert(result.action === 'skipped-no-session', 'expected missing session skip');
39+
}));
40+
41+
results.push(await runCase('refreshes snapshot on PostToolUse', async () => {
42+
let refreshed = 0;
43+
const result = await handleSessionStateEvent(
44+
{ hook_event_name: 'PostToolUse', session_id: 'abc' },
45+
{
46+
enabled: true,
47+
refresh: async () => {
48+
refreshed += 1;
49+
return { success: true };
50+
},
51+
persist: () => ({ success: false })
52+
}
53+
);
54+
assert(refreshed === 1, 'expected one refresh');
55+
assert(result.refreshed === true, 'expected refreshed flag');
56+
assert(result.persisted === false, 'expected no persist');
57+
}));
58+
59+
results.push(await runCase('persists and refreshes on Stop', async () => {
60+
let persisted = 0;
61+
let refreshed = 0;
62+
const result = await handleSessionStateEvent(
63+
{ hook_event_name: 'Stop', session_id: 'abc', cwd: process.cwd() },
64+
{
65+
enabled: true,
66+
refresh: async () => {
67+
refreshed += 1;
68+
return { success: true };
69+
},
70+
persist: () => {
71+
persisted += 1;
72+
return { success: true };
73+
}
74+
}
75+
);
76+
assert(persisted === 1, 'expected one persist');
77+
assert(refreshed === 1, 'expected one refresh');
78+
assert(result.persisted === true, 'expected persisted flag');
79+
assert(result.refreshed === true, 'expected refreshed flag');
80+
}));
81+
82+
if (results.every(Boolean)) return;
83+
process.exit(1);
84+
}
85+
86+
run().catch((error) => {
87+
console.error(error);
88+
process.exit(1);
89+
});
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Statusline Test Suite
2+
3+
Comprehensive tests for `.claude/statusline.cjs` and supporting libraries.
4+
5+
## Files
6+
7+
- `usage-limits-cache.test.cjs` - Unit tests for the usage quota cache helper (5 tests)
8+
- `statusline.test.cjs` - Unit/regression tests for helpers and parser logic (57 tests)
9+
- `statusline-integration.test.cjs` - End-to-end rendering tests for `statusline.cjs` (30 tests)
10+
- `statusline-scenarios.test.cjs` - Cross-platform and user workflow scenarios (19 tests)
11+
- `statusline-suite.cjs` - Aggregate runner for all statusline suites
12+
- `vc-config-utils.test.cjs` - Existing config utility coverage
13+
14+
## Running Tests
15+
16+
```bash
17+
# From repository root
18+
node .claude/hooks/lib/__tests__/statusline-suite.cjs
19+
```
20+
21+
Run individual suites when debugging:
22+
23+
```bash
24+
node .claude/hooks/lib/__tests__/usage-limits-cache.test.cjs
25+
node .claude/hooks/lib/__tests__/statusline.test.cjs
26+
node .claude/hooks/lib/__tests__/statusline-integration.test.cjs
27+
node .claude/hooks/lib/__tests__/statusline-scenarios.test.cjs
28+
```
29+
30+
## Current Coverage Scope
31+
32+
### Usage Cache Helper (`usage-limits-cache.test.cjs`)
33+
- live OAuth whole-number percentage handling plus defensive `0..1` fallback
34+
- additive `snapshot` generation for cosmetic `5h` / `wk` chips
35+
- cache age helpers that keep refresh work off the render path
36+
- success and failure writes for the shared quota cache file
37+
38+
### Unit and Regression (`statusline.test.cjs`)
39+
- color behavior and ANSI toggles (`NO_COLOR`, `FORCE_COLOR`)
40+
- context thresholds and bar rendering
41+
- transcript parsing and target extraction
42+
- native task mapping (`TaskCreate`/`TaskUpdate`/`TaskGet`/`TaskList`)
43+
- stdin timeout and fallback behavior
44+
- usage cache parse and render behavior
45+
- git info cache timeout race regressions
46+
47+
### End-to-End (`statusline-integration.test.cjs`)
48+
- minimal/default payload rendering
49+
- git workspace behavior
50+
- context usage and cost display paths
51+
- invalid/empty input fallback handling
52+
- home path shortening and multi-line behavior
53+
- environment behavior (`NO_COLOR`, billing mode)
54+
55+
### Scenario Suite (`statusline-scenarios.test.cjs`)
56+
- Linux/macOS/Windows/UNC/WSL path rendering
57+
- statusline modes (`none`, `minimal`, `compact`, default/full)
58+
- delayed stdin and optional timeout (`CK_STATUSLINE_STDIN_TIMEOUT_MS`)
59+
- normalized snapshot rendering, legacy raw cache fallback, and unavailable cache behavior
60+
- display remaining visible when `usage-context-awareness` is disabled
61+
- native task transcript flows and legacy TodoWrite coexistence
62+
- terminal width wrapping (wide + narrow unicode paths)
63+
64+
## Latest Verified Result
65+
66+
- total tests: 111
67+
- passed: 111
68+
- failed: 0
69+
- suites run: 4
70+
71+
## Maintenance
72+
73+
When changing statusline logic:
74+
75+
1. Update/add tests in the relevant suite.
76+
2. Run the aggregate suite:
77+
```bash
78+
node .claude/hooks/lib/__tests__/statusline-suite.cjs
79+
```
80+
3. Keep this README counts and scope notes in sync with test changes.
81+
82+
## Related Files
83+
84+
- `/.claude/statusline.cjs`
85+
- `/.claude/hooks/lib/colors.cjs`
86+
- `/.claude/hooks/lib/transcript-parser.cjs`
87+
- `/.claude/hooks/lib/config-counter.cjs`
88+
- `/.claude/hooks/lib/git-info-cache.cjs`
89+
90+
**Last Updated:** 2026-02-26
91+
**Status:** passing

0 commit comments

Comments
 (0)