company-skill 3.0.0 → 3.1.1

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.
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ // PostToolUse on Edit/Write: run compiler/linter immediately after code changes.
4
+ // Catches errors before Claude moves on to the next task.
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { execSync } = require('child_process');
9
+
10
+ // Read tool input from stdin
11
+ let input = '';
12
+ try { input = fs.readFileSync('/dev/stdin', 'utf8'); } catch (e) {}
13
+
14
+ let filePath;
15
+ try {
16
+ const data = JSON.parse(input);
17
+ filePath = data.tool_response?.filePath || data.tool_input?.file_path;
18
+ } catch (e) {}
19
+
20
+ if (!filePath) process.exit(0);
21
+
22
+ const ext = path.extname(filePath);
23
+ let cmd = null;
24
+
25
+ if (['.ts', '.tsx'].includes(ext)) cmd = `npx tsc --noEmit "${filePath}" 2>&1 | head -5`;
26
+ else if (['.js', '.jsx'].includes(ext)) cmd = `node --check "${filePath}" 2>&1`;
27
+ else if (ext === '.py') cmd = `python3 -c "import py_compile; py_compile.compile('${filePath}', doraise=True)" 2>&1`;
28
+ else if (ext === '.json') cmd = `node -e "JSON.parse(require('fs').readFileSync('${filePath}','utf8'))" 2>&1`;
29
+
30
+ if (!cmd) process.exit(0);
31
+
32
+ try {
33
+ execSync(cmd, { timeout: 10000 });
34
+ } catch (e) {
35
+ const err = (e.stdout?.toString() || e.message).substring(0, 300);
36
+ console.log(JSON.stringify({
37
+ systemMessage: "Compile/syntax error in " + path.basename(filePath) + ": " + err
38
+ }));
39
+ }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Save company state before context compaction so nothing is lost.
3
+ // Save company state AND reasoning before context compaction.
4
+ // Saves both numbers (criteria, cycle) and intent (what we're trying and why).
4
5
 
5
6
  const fs = require('fs');
6
7
  const path = require('path');
@@ -8,39 +9,74 @@ const path = require('path');
8
9
  const companyDir = path.join(process.cwd(), '.company');
9
10
  if (!fs.existsSync(companyDir)) process.exit(0);
10
11
 
11
- const checkpoint = {};
12
+ const lines = ['# Company Checkpoint (auto-saved before compaction)', ''];
12
13
 
13
- // Save current cycle number
14
+ // Goal
15
+ const goalPath = path.join(companyDir, 'GOAL.md');
16
+ if (fs.existsSync(goalPath)) {
17
+ lines.push('## Goal');
18
+ lines.push(fs.readFileSync(goalPath, 'utf8').substring(0, 500));
19
+ lines.push('');
20
+ }
21
+
22
+ // Cycle number
14
23
  const cyclesDir = path.join(companyDir, 'cycles');
15
24
  if (fs.existsSync(cyclesDir)) {
16
25
  const files = fs.readdirSync(cyclesDir).filter(f => f.startsWith('cycle-'));
17
26
  const nums = files.map(f => parseInt(f.match(/cycle-(\d+)/)?.[1] || '0'));
18
- checkpoint.cycle = Math.max(0, ...nums);
27
+ const cycle = Math.max(0, ...nums);
28
+ lines.push('## Cycle: ' + cycle);
29
+ lines.push('');
30
+
31
+ // Latest briefing (captures current reasoning/intent)
32
+ const briefing = path.join(cyclesDir, `cycle-${cycle}-briefing.md`);
33
+ if (fs.existsSync(briefing)) {
34
+ lines.push('## Current Reasoning');
35
+ lines.push(fs.readFileSync(briefing, 'utf8').substring(0, 1000));
36
+ lines.push('');
37
+ }
38
+
39
+ // Latest review (captures what's working/failing)
40
+ const review = path.join(cyclesDir, `cycle-${cycle}-review.md`);
41
+ if (fs.existsSync(review)) {
42
+ lines.push('## Latest Review');
43
+ lines.push(fs.readFileSync(review, 'utf8').substring(0, 500));
44
+ lines.push('');
45
+ }
19
46
  }
20
47
 
21
- // Save criteria status
48
+ // Criteria status
22
49
  const criteriaPath = path.join(companyDir, 'criteria.json');
23
50
  if (fs.existsSync(criteriaPath)) {
24
51
  try {
25
52
  const data = JSON.parse(fs.readFileSync(criteriaPath, 'utf8'));
26
53
  const all = data.criteria || [];
27
- checkpoint.goal = data.goal;
28
- checkpoint.passing = all.filter(c => c.passes).length;
29
- checkpoint.total = all.length;
30
- checkpoint.failing = all.filter(c => !c.passes).map(c => c.description);
54
+ lines.push('## Criteria: ' + all.filter(c => c.passes).length + '/' + all.length + ' passing');
55
+ for (const c of all) {
56
+ lines.push('- [' + (c.passes ? 'x' : ' ') + '] ' + c.description);
57
+ }
58
+ lines.push('');
31
59
  } catch (e) {}
32
60
  }
33
61
 
34
- // Save active roster
62
+ // Active roster
35
63
  const rosterPath = path.join(companyDir, 'active-roster.md');
36
64
  if (fs.existsSync(rosterPath)) {
37
- checkpoint.roster = fs.readFileSync(rosterPath, 'utf8').substring(0, 500);
65
+ lines.push('## Active Roster');
66
+ lines.push(fs.readFileSync(rosterPath, 'utf8').substring(0, 300));
67
+ lines.push('');
68
+ }
69
+
70
+ // Playbook (accumulated lessons)
71
+ const playbookPath = path.join(companyDir, 'playbook.md');
72
+ if (fs.existsSync(playbookPath)) {
73
+ lines.push('## Playbook (lessons)');
74
+ lines.push(fs.readFileSync(playbookPath, 'utf8').substring(0, 500));
75
+ lines.push('');
38
76
  }
39
77
 
40
- // Write checkpoint
41
- fs.writeFileSync(
42
- path.join(companyDir, '.checkpoint.json'),
43
- JSON.stringify(checkpoint, null, 2)
44
- );
78
+ lines.push('## Next Action');
79
+ lines.push('Read .company/criteria.json and continue THINK > EXECUTE > VERIFY.');
45
80
 
81
+ fs.writeFileSync(path.join(companyDir, '.checkpoint.md'), lines.join('\n'));
46
82
  process.exit(0);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Restore company state after compaction/resume. Injects context via systemMessage.
3
+ // Restore company state after compaction. Reads the checkpoint with reasoning + state.
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
@@ -8,27 +8,23 @@ const path = require('path');
8
8
  const companyDir = path.join(process.cwd(), '.company');
9
9
  if (!fs.existsSync(companyDir)) process.exit(0);
10
10
 
11
- const checkpointPath = path.join(companyDir, '.checkpoint.json');
12
- if (!fs.existsSync(checkpointPath)) process.exit(0);
13
-
14
- try {
15
- const cp = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
16
- const msg = [
17
- "[COMPANY RESTORED] Session was compacted. Resuming.",
18
- "Goal: " + (cp.goal || "unknown"),
19
- "Cycle: " + (cp.cycle || 0),
20
- "Criteria: " + (cp.passing || 0) + "/" + (cp.total || 0) + " passing",
21
- ];
22
-
23
- if (cp.failing && cp.failing.length > 0) {
24
- msg.push("Failing: " + cp.failing.join(", "));
25
- }
26
-
27
- msg.push("Read .company/criteria.json and continue THINK > EXECUTE > VERIFY.");
11
+ const checkpointMd = path.join(companyDir, '.checkpoint.md');
12
+ const checkpointJson = path.join(companyDir, '.checkpoint.json');
13
+
14
+ let msg = null;
15
+
16
+ if (fs.existsSync(checkpointMd)) {
17
+ msg = fs.readFileSync(checkpointMd, 'utf8').substring(0, 2000);
18
+ } else if (fs.existsSync(checkpointJson)) {
19
+ try {
20
+ const cp = JSON.parse(fs.readFileSync(checkpointJson, 'utf8'));
21
+ msg = "[COMPANY RESTORED] Goal: " + (cp.goal || "unknown") +
22
+ ", Cycle: " + (cp.cycle || 0) +
23
+ ", Criteria: " + (cp.passing || 0) + "/" + (cp.total || 0) +
24
+ ". Read .company/criteria.json and continue.";
25
+ } catch (e) {}
26
+ }
28
27
 
29
- console.log(JSON.stringify({
30
- systemMessage: msg.join("\n")
31
- }));
32
- } catch (e) {
33
- process.exit(0);
28
+ if (msg) {
29
+ console.log(JSON.stringify({ systemMessage: msg }));
34
30
  }
@@ -21,15 +21,7 @@ if (fs.existsSync(cancelPath)) {
21
21
  process.exit(0);
22
22
  }
23
23
 
24
- // Circuit breaker: max 10 blocks then allow stop
25
- let count = 0;
26
- try { count = parseInt(fs.readFileSync(counterPath, 'utf8')) || 0; } catch (e) {}
27
- count++;
28
- try { fs.writeFileSync(counterPath, String(count)); } catch (e) {}
29
- if (count > 10) {
30
- try { fs.unlinkSync(counterPath); } catch (e) {}
31
- process.exit(0); // Allow stop, prevent infinite loop
32
- }
24
+ // No limit. Runs until done or user cancels (touch .company/CANCEL).
33
25
 
34
26
  // Check criteria
35
27
  if (fs.existsSync(criteriaPath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "company-skill",
3
- "version": "3.0.0",
3
+ "version": "3.1.1",
4
4
  "description": "Goal-driven multi-employee company for Claude Code. Give it a goal, it runs until done.",
5
5
  "bin": {
6
6
  "company-skill": "./bin/install.js"