@dommaker/harness 0.12.9 β 0.12.11
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/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +9 -13
- package/dist/cli/commands/release.js.map +1 -1
- package/package.json +2 -2
- package/bin/harness-knowledge-capture.js +0 -99
- package/bin/harness-knowledge-check.js +0 -63
- package/bin/harness-knowledge-track.js +0 -92
- package/bin/harness-knowledge-track.sh +0 -34
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiIpE"}
|
|
@@ -150,22 +150,18 @@ async function release(options) {
|
|
|
150
150
|
const origRegistry = await run('npm config get registry', pkgPath);
|
|
151
151
|
await run('npm config set registry https://registry.npmjs.org/', pkgPath);
|
|
152
152
|
console.log(chalk_1.default.cyan('π€ Publishing to npm...'));
|
|
153
|
-
//
|
|
154
|
-
const pub = await run('npm publish
|
|
155
|
-
// Restore original registry
|
|
153
|
+
// npm publish to npmjs.org (the write registry β npmmirror is read-only)
|
|
154
|
+
const pub = await run('npm publish --registry https://registry.npmjs.org/', pkgPath, 180_000);
|
|
155
|
+
// Restore original registry
|
|
156
156
|
await run(`npm config set registry ${origRegistry.stdout}`, pkgPath);
|
|
157
|
-
//
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!pubOutput.includes('previously published') && !pubOutput.includes('EPUBLISHCONFLICT')) {
|
|
162
|
-
console.error(chalk_1.default.red('β npm publish failed:'), pubOutput.slice(0, 500));
|
|
163
|
-
process.exit(1);
|
|
164
|
-
}
|
|
165
|
-
console.log(chalk_1.default.yellow(`β οΈ npm: ${pkgName}@${newVersion} already published (skipping)`));
|
|
157
|
+
// Don't string-match npm output β verify by querying the registry
|
|
158
|
+
const verify = await run(`npm view ${pkgName} version --registry https://registry.npmjs.org/`, pkgPath);
|
|
159
|
+
if (verify.stdout.trim() === newVersion) {
|
|
160
|
+
console.log(chalk_1.default.green(`β
npm: published ${pkgName}@${newVersion}`));
|
|
166
161
|
}
|
|
167
162
|
else {
|
|
168
|
-
console.log(chalk_1.default.
|
|
163
|
+
console.log(chalk_1.default.red(`β npm publish verification failed. Expected ${newVersion}, registry has ${verify.stdout.trim() || '???'}`));
|
|
164
|
+
process.exit(1);
|
|
169
165
|
}
|
|
170
166
|
// ββ 9. GitHub Release ββ
|
|
171
167
|
console.log(chalk_1.default.cyan('π Creating GitHub Release...'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBH,
|
|
1
|
+
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../../src/cli/commands/release.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dommaker/harness",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.11",
|
|
4
4
|
"description": "ιη¨ε·₯η¨ηΊ¦ζζ‘ζΆ - ιεΎη³»η»γζ£ζ₯ηΉιͺθ―γζ΅θ―ι¨ζ§γζ¦ζͺε¨",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"harness",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist",
|
|
43
|
-
"bin",
|
|
43
|
+
"bin/harness.js",
|
|
44
44
|
"templates",
|
|
45
45
|
"github-actions"
|
|
46
46
|
],
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Harness Knowledge Capture Hook
|
|
4
|
-
*
|
|
5
|
-
* Runs as an afterTurn hook in Claude Code.
|
|
6
|
-
* Detects deep analysis (β₯3 source files read) without knowledge-doc output,
|
|
7
|
-
* and warns the user that knowledge may need to be captured.
|
|
8
|
-
*
|
|
9
|
-
* Usage (in settings.json):
|
|
10
|
-
* "hooks": {
|
|
11
|
-
* "afterTurn": [{
|
|
12
|
-
* "command": "node ~/projects/harness/bin/harness-knowledge-capture.js"
|
|
13
|
-
* }]
|
|
14
|
-
* }
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const fs = require('fs');
|
|
18
|
-
const path = require('path');
|
|
19
|
-
|
|
20
|
-
// Read turn data from stdin
|
|
21
|
-
let input = '';
|
|
22
|
-
process.stdin.setEncoding('utf-8');
|
|
23
|
-
process.stdin.on('data', (chunk) => input += chunk);
|
|
24
|
-
|
|
25
|
-
process.stdin.on('end', () => {
|
|
26
|
-
try {
|
|
27
|
-
const turn = JSON.parse(input);
|
|
28
|
-
const result = checkTurn(turn);
|
|
29
|
-
if (result.shouldWarn) {
|
|
30
|
-
process.stderr.write(`\n${'='.repeat(60)}\n`);
|
|
31
|
-
process.stderr.write(' β οΈ ε―θ½ιζΌδΊη₯θ―ζ²ζ·\n');
|
|
32
|
-
process.stderr.write(`${'='.repeat(60)}\n`);
|
|
33
|
-
process.stderr.write(` ζ¬εεθ―»εδΊ ${result.fileReads} δΈͺζδ»Ά\n`);
|
|
34
|
-
process.stderr.write(` δ½ζͺεε
₯ .harness/knowledge-docs/\n`);
|
|
35
|
-
process.stderr.write(`\n`);
|
|
36
|
-
process.stderr.write(` ε¦ζθΏζ―ζ·±εΊ¦εζοΌθ―·ζ§θ‘οΌ\n`);
|
|
37
|
-
process.stderr.write(` npx harness knowledge upsert --scope <scope> --file <file> --source claude\n`);
|
|
38
|
-
process.stderr.write(`${'='.repeat(60)}\n\n`);
|
|
39
|
-
}
|
|
40
|
-
} catch (e) {
|
|
41
|
-
// Silently ignore parse errors β non-JSON input is fine
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
function checkTurn(turn) {
|
|
46
|
-
let fileReads = 0;
|
|
47
|
-
let knowledgeWrites = 0;
|
|
48
|
-
|
|
49
|
-
// Walk through messages looking for tool calls
|
|
50
|
-
const messages = turn.messages || [turn];
|
|
51
|
-
for (const msg of messages) {
|
|
52
|
-
// Claude Code format: tool_uses array
|
|
53
|
-
if (msg.role === 'assistant' && msg.tool_uses) {
|
|
54
|
-
for (const tool of msg.tool_uses) {
|
|
55
|
-
if (isFileRead(tool)) fileReads++;
|
|
56
|
-
if (isKnowledgeWrite(tool)) knowledgeWrites++;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// Plain tool_calls format
|
|
60
|
-
if (msg.tool_calls) {
|
|
61
|
-
for (const tool of msg.tool_calls) {
|
|
62
|
-
if (isFileRead(tool)) fileReads++;
|
|
63
|
-
if (isKnowledgeWrite(tool)) knowledgeWrites++;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// Messages content with tool use markers
|
|
67
|
-
if (msg.content && typeof msg.content === 'string') {
|
|
68
|
-
const readMatches = msg.content.match(/\bRead\b.*/g);
|
|
69
|
-
if (readMatches) fileReads += readMatches.length;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
fileReads,
|
|
75
|
-
knowledgeWrites,
|
|
76
|
-
shouldWarn: fileReads >= 3 && knowledgeWrites === 0,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function isFileRead(tool) {
|
|
81
|
-
const name = (tool.name || tool.function?.name || '').toLowerCase();
|
|
82
|
-
const isReadTool = ['read', 'glob', 'grep', 'agent'].includes(name);
|
|
83
|
-
if (!isReadTool) return false;
|
|
84
|
-
|
|
85
|
-
const params = tool.parameters || tool.function?.arguments || {};
|
|
86
|
-
const filePath = params.file_path || params.path || params.pattern || '';
|
|
87
|
-
// Only count actual source file reads, not config/memory/docs
|
|
88
|
-
const isSource = /\/(src|packages|apps)\/|\.(ts|tsx|js|jsx|py|go|rs)$/.test(filePath);
|
|
89
|
-
return isSource;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function isKnowledgeWrite(tool) {
|
|
93
|
-
const name = (tool.name || tool.function?.name || '').toLowerCase();
|
|
94
|
-
if (name !== 'write') return false;
|
|
95
|
-
|
|
96
|
-
const params = tool.parameters || tool.function?.arguments || {};
|
|
97
|
-
const filePath = params.file_path || '';
|
|
98
|
-
return filePath.includes('.harness/knowledge-docs/') || filePath.includes('.harness/knowledge/');
|
|
99
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Stop hook β check if deep analysis happened without knowledge capture
|
|
4
|
-
*
|
|
5
|
-
* Reads state file written by harness-knowledge-track.js.
|
|
6
|
-
* If EnterPlanMode was called, or Agent(Explore) was spawned, or 10+ unique
|
|
7
|
-
* directories were Read β and no knowledge files were Written β warn.
|
|
8
|
-
*
|
|
9
|
-
* Output: JSON with systemMessage (shown to user)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const STATE_FILE = '/tmp/claude-knowledge-capture-state.json';
|
|
14
|
-
const LOG_FILE = '/tmp/claude-knowledge-hooks.log';
|
|
15
|
-
const UNIQUE_DIR_THRESHOLD = 10;
|
|
16
|
-
|
|
17
|
-
function log(level, message, data) {
|
|
18
|
-
try {
|
|
19
|
-
const entry = JSON.stringify({ ts: new Date().toISOString(), level, message, ...data }) + '\n';
|
|
20
|
-
fs.appendFileSync(LOG_FILE, entry, 'utf-8');
|
|
21
|
-
} catch {}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
if (!fs.existsSync(STATE_FILE)) process.exit(0);
|
|
26
|
-
|
|
27
|
-
const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
|
|
28
|
-
const deepAnalysis = state.planned || state.explored || state.readDirs.length >= UNIQUE_DIR_THRESHOLD;
|
|
29
|
-
const missingCapture = !state.captured;
|
|
30
|
-
|
|
31
|
-
log('info', 'stop-check', {
|
|
32
|
-
planned: state.planned, explored: state.explored,
|
|
33
|
-
readDirsCount: state.readDirs.length, captured: state.captured,
|
|
34
|
-
deepAnalysis, missingCapture,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (deepAnalysis && missingCapture) {
|
|
38
|
-
const signals = [];
|
|
39
|
-
if (state.planned) signals.push('EnterPlanMode called');
|
|
40
|
-
if (state.explored) signals.push('Agent(Explore) spawned');
|
|
41
|
-
if (state.readDirs.length >= UNIQUE_DIR_THRESHOLD) signals.push(`${state.readDirs.length} unique directories Read`);
|
|
42
|
-
|
|
43
|
-
log('warn', 'missing-capture', { signals });
|
|
44
|
-
|
|
45
|
-
const message = [
|
|
46
|
-
'β οΈ Deep analysis detected but no knowledge captured.',
|
|
47
|
-
` Signals: ${signals.join(', ')}`,
|
|
48
|
-
'',
|
|
49
|
-
' To capture:',
|
|
50
|
-
' 1. Write .harness/knowledge-docs/<scope>.md',
|
|
51
|
-
' 2. npx harness knowledge upsert --scope <scope> --file <file> --source claude',
|
|
52
|
-
'',
|
|
53
|
-
' Or run `harness knowledge sync-status` to check staleness.',
|
|
54
|
-
].join('\n');
|
|
55
|
-
|
|
56
|
-
console.log(JSON.stringify({ systemMessage: message }));
|
|
57
|
-
}
|
|
58
|
-
} catch (e) {
|
|
59
|
-
// Silently ignore errors
|
|
60
|
-
} finally {
|
|
61
|
-
// Clean up state file for next session
|
|
62
|
-
try { fs.unlinkSync(STATE_FILE); } catch {}
|
|
63
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* PostToolUse hook β track deep analysis signals
|
|
4
|
-
*
|
|
5
|
-
* Updates state file with:
|
|
6
|
-
* - planned: EnterPlanMode was called
|
|
7
|
-
* - explored: Agent(Explore) was spawned
|
|
8
|
-
* - readDirs: Set of unique directories Read was called on
|
|
9
|
-
* - captured: Write to .harness/knowledge-docs/ or .harness/knowledge/
|
|
10
|
-
* - turnCount: session turn counter
|
|
11
|
-
*
|
|
12
|
-
* Usage: PostToolUse hook with matcher "EnterPlanMode|Agent|Read|Write|Write"
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const fs = require('fs');
|
|
16
|
-
const path = require('path');
|
|
17
|
-
|
|
18
|
-
const STATE_FILE = '/tmp/claude-knowledge-capture-state.json';
|
|
19
|
-
const LOG_FILE = '/tmp/claude-knowledge-hooks.log';
|
|
20
|
-
|
|
21
|
-
function log(level, message, data) {
|
|
22
|
-
try {
|
|
23
|
-
const entry = JSON.stringify({ ts: new Date().toISOString(), level, message, ...data }) + '\n';
|
|
24
|
-
fs.appendFileSync(LOG_FILE, entry, 'utf-8');
|
|
25
|
-
} catch {}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Read hook input from stdin
|
|
29
|
-
let input = '';
|
|
30
|
-
process.stdin.setEncoding('utf-8');
|
|
31
|
-
process.stdin.on('data', (chunk) => input += chunk);
|
|
32
|
-
|
|
33
|
-
process.stdin.on('end', () => {
|
|
34
|
-
try {
|
|
35
|
-
const event = JSON.parse(input);
|
|
36
|
-
const state = loadState();
|
|
37
|
-
updateState(state, event);
|
|
38
|
-
saveState(state);
|
|
39
|
-
} catch (e) {
|
|
40
|
-
// Silently ignore parse errors
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
function loadState() {
|
|
45
|
-
try {
|
|
46
|
-
if (fs.existsSync(STATE_FILE)) {
|
|
47
|
-
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
|
|
48
|
-
}
|
|
49
|
-
} catch {}
|
|
50
|
-
return { planned: false, explored: false, readDirs: [], captured: false };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function updateState(state, event) {
|
|
54
|
-
const toolName = event.tool_name || '';
|
|
55
|
-
|
|
56
|
-
if (toolName === 'EnterPlanMode') {
|
|
57
|
-
state.planned = true;
|
|
58
|
-
log('info', 'planned', { tool: toolName });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (toolName === 'Agent') {
|
|
62
|
-
const input = event.tool_input || {};
|
|
63
|
-
if (input.subagent_type === 'Explore') {
|
|
64
|
-
state.explored = true;
|
|
65
|
-
log('info', 'explored', { tool: toolName, subagent_type: input.subagent_type });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (toolName === 'Read') {
|
|
70
|
-
const input = event.tool_input || {};
|
|
71
|
-
const filePath = input.file_path || '';
|
|
72
|
-
const dir = path.dirname(filePath);
|
|
73
|
-
if (dir && dir !== '.' && dir !== '/' && !state.readDirs.includes(dir)) {
|
|
74
|
-
state.readDirs.push(dir);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (toolName === 'Write') {
|
|
79
|
-
const input = event.tool_input || {};
|
|
80
|
-
const filePath = input.file_path || '';
|
|
81
|
-
if (filePath.includes('.harness/knowledge-docs/') || filePath.includes('.harness/knowledge/')) {
|
|
82
|
-
state.captured = true;
|
|
83
|
-
log('info', 'captured', { file: filePath });
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function saveState(state) {
|
|
89
|
-
try {
|
|
90
|
-
fs.writeFileSync(STATE_FILE, JSON.stringify(state), 'utf-8');
|
|
91
|
-
} catch {}
|
|
92
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# PostToolUse hook β track deep analysis signals
|
|
3
|
-
# Replaces Node.js version. Bash: <1ms vs Node: 33ms cold start.
|
|
4
|
-
# Matcher: Read|Write (most frequent tools, covers all signals needed)
|
|
5
|
-
|
|
6
|
-
STATE_FILE=/tmp/claude-knowledge-capture-state.json
|
|
7
|
-
INPUT=$(cat)
|
|
8
|
-
|
|
9
|
-
tool_name=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
10
|
-
file_path=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
|
|
11
|
-
|
|
12
|
-
# Init state file if missing
|
|
13
|
-
[ -f "$STATE_FILE" ] || echo '{"planned":false,"explored":false,"readDirs":[],"captured":false}' > "$STATE_FILE"
|
|
14
|
-
|
|
15
|
-
case "$tool_name" in
|
|
16
|
-
EnterPlanMode)
|
|
17
|
-
jq '.planned = true' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
|
18
|
-
;;
|
|
19
|
-
Read)
|
|
20
|
-
if [ -n "$file_path" ]; then
|
|
21
|
-
dir=$(dirname "$file_path")
|
|
22
|
-
if [ "$dir" != "." ] && [ "$dir" != "/" ]; then
|
|
23
|
-
jq --arg d "$dir" '.readDirs += [$d] | .readDirs |= unique' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
|
24
|
-
fi
|
|
25
|
-
fi
|
|
26
|
-
;;
|
|
27
|
-
Write)
|
|
28
|
-
case "$file_path" in
|
|
29
|
-
*.harness/knowledge-docs/*|*.harness/knowledge/*)
|
|
30
|
-
jq '.captured = true' "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
|
|
31
|
-
;;
|
|
32
|
-
esac
|
|
33
|
-
;;
|
|
34
|
-
esac
|