@grainulation/wheat 1.0.0

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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/bin/wheat.js +193 -0
  4. package/compiler/detect-sprints.js +319 -0
  5. package/compiler/generate-manifest.js +280 -0
  6. package/compiler/wheat-compiler.js +1229 -0
  7. package/lib/compiler.js +35 -0
  8. package/lib/connect.js +418 -0
  9. package/lib/disconnect.js +188 -0
  10. package/lib/guard.js +151 -0
  11. package/lib/index.js +14 -0
  12. package/lib/init.js +457 -0
  13. package/lib/install-prompt.js +186 -0
  14. package/lib/quickstart.js +276 -0
  15. package/lib/serve-mcp.js +509 -0
  16. package/lib/server.js +391 -0
  17. package/lib/stats.js +184 -0
  18. package/lib/status.js +135 -0
  19. package/lib/update.js +71 -0
  20. package/package.json +53 -0
  21. package/public/index.html +1798 -0
  22. package/templates/claude.md +122 -0
  23. package/templates/commands/blind-spot.md +47 -0
  24. package/templates/commands/brief.md +73 -0
  25. package/templates/commands/calibrate.md +39 -0
  26. package/templates/commands/challenge.md +72 -0
  27. package/templates/commands/connect.md +104 -0
  28. package/templates/commands/evaluate.md +80 -0
  29. package/templates/commands/feedback.md +60 -0
  30. package/templates/commands/handoff.md +53 -0
  31. package/templates/commands/init.md +68 -0
  32. package/templates/commands/merge.md +51 -0
  33. package/templates/commands/present.md +52 -0
  34. package/templates/commands/prototype.md +68 -0
  35. package/templates/commands/replay.md +61 -0
  36. package/templates/commands/research.md +73 -0
  37. package/templates/commands/resolve.md +42 -0
  38. package/templates/commands/status.md +56 -0
  39. package/templates/commands/witness.md +79 -0
  40. package/templates/explainer.html +343 -0
package/lib/status.js ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * wheat status — Quick sprint status check
3
+ *
4
+ * Runs the compiler in summary mode against the target directory.
5
+ * Provides a fast terminal snapshot of sprint health.
6
+ *
7
+ * Zero npm dependencies.
8
+ */
9
+
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ import { compile } from '../compiler/wheat-compiler.js';
13
+
14
+ export async function run(dir, args) {
15
+ const jsonMode = args.includes('--json');
16
+ const claimsPath = path.join(dir, 'claims.json');
17
+
18
+ if (!fs.existsSync(claimsPath)) {
19
+ if (jsonMode) {
20
+ console.log(JSON.stringify({ error: 'no_sprint', message: 'No sprint found in this directory.' }));
21
+ process.exit(0);
22
+ }
23
+ console.log();
24
+ console.log(' No sprint found in this directory.');
25
+ console.log(' Run "wheat init" to start a research sprint.');
26
+ console.log();
27
+ process.exit(0);
28
+ }
29
+
30
+ const claimsData = JSON.parse(fs.readFileSync(claimsPath, 'utf8'));
31
+ const compilationPath = path.join(dir, 'compilation.json');
32
+ const compilation = compile(claimsPath, compilationPath, dir);
33
+
34
+ const meta = claimsData.meta || {};
35
+ const claims = claimsData.claims || [];
36
+ const active = claims.filter(c => c.status === 'active');
37
+ const superseded = claims.filter(c => c.status === 'superseded');
38
+
39
+ if (jsonMode) {
40
+ const tiers = {};
41
+ for (const c of active) {
42
+ tiers[c.evidence] = (tiers[c.evidence] || 0) + 1;
43
+ }
44
+ const result = {
45
+ question: meta.question || null,
46
+ phase: meta.phase || 'unknown',
47
+ status: compilation.status,
48
+ claims: { total: claims.length, active: active.length, superseded: superseded.length },
49
+ evidence: tiers,
50
+ };
51
+ if (compilation.conflicts) {
52
+ result.conflicts = {
53
+ resolved: compilation.conflicts.resolved.length,
54
+ unresolved: compilation.conflicts.unresolved.length,
55
+ };
56
+ }
57
+ if (compilation.coverage) {
58
+ result.topics = Object.keys(compilation.coverage);
59
+ }
60
+ if (meta.initiated) {
61
+ const days = Math.floor((Date.now() - new Date(meta.initiated).getTime()) / 86400000);
62
+ result.age = { days, initiated: meta.initiated };
63
+ }
64
+ console.log(JSON.stringify(result, null, 2));
65
+ process.exit(0);
66
+ }
67
+
68
+ const icon = compilation.status === 'ready' ? '\x1b[32m●\x1b[0m' : '\x1b[31m●\x1b[0m';
69
+
70
+ console.log();
71
+ console.log(` ${icon} \x1b[1m${meta.question || 'No question set'}\x1b[0m`);
72
+ console.log(` ${'─'.repeat(50)}`);
73
+ console.log(` Phase: ${meta.phase || 'unknown'}`);
74
+ console.log(` Status: ${compilation.status}`);
75
+ console.log(` Claims: ${claims.length} total, ${active.length} active, ${superseded.length} superseded`);
76
+
77
+ // Evidence breakdown
78
+ const tiers = {};
79
+ for (const c of active) {
80
+ tiers[c.evidence] = (tiers[c.evidence] || 0) + 1;
81
+ }
82
+ const tierStr = Object.entries(tiers).map(([k, v]) => `${k}:${v}`).join(' ');
83
+ if (tierStr) {
84
+ console.log(` Evidence: ${tierStr}`);
85
+ }
86
+
87
+ // Conflicts
88
+ if (compilation.conflicts) {
89
+ const { resolved, unresolved } = compilation.conflicts;
90
+ if (resolved.length > 0 || unresolved.length > 0) {
91
+ console.log(` Conflicts: ${resolved.length} resolved, ${unresolved.length} unresolved`);
92
+ }
93
+ }
94
+
95
+ // Topics
96
+ if (compilation.coverage) {
97
+ const topics = Object.keys(compilation.coverage);
98
+ console.log(` Topics: ${topics.length} (${topics.join(', ')})`);
99
+ }
100
+
101
+ // Initiated
102
+ if (meta.initiated) {
103
+ const days = Math.floor((Date.now() - new Date(meta.initiated).getTime()) / 86400000);
104
+ console.log(` Age: ${days} days (since ${meta.initiated})`);
105
+ }
106
+
107
+ console.log();
108
+
109
+ // Suggest next steps based on state
110
+ console.log(' Next steps:');
111
+
112
+ if (compilation.conflicts?.unresolved?.length > 0) {
113
+ console.log(' /resolve — resolve unresolved conflicts');
114
+ }
115
+
116
+ const weakTopics = Object.entries(compilation.coverage || {})
117
+ .filter(([, d]) => d.max_evidence === 'stated' || d.max_evidence === 'web')
118
+ .map(([t]) => t);
119
+
120
+ if (weakTopics.length > 0) {
121
+ console.log(` /research — strengthen weak topics: ${weakTopics.join(', ')}`);
122
+ }
123
+
124
+ if (meta.phase === 'define') {
125
+ console.log(' /research <topic> — start investigating');
126
+ } else if (meta.phase === 'research') {
127
+ console.log(' /prototype — test your findings');
128
+ } else if (meta.phase === 'prototype' || meta.phase === 'evaluate') {
129
+ if (compilation.status === 'ready') {
130
+ console.log(' /brief — compile the decision document');
131
+ }
132
+ }
133
+
134
+ console.log();
135
+ }
package/lib/update.js ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * wheat update — Copy/update slash commands to .claude/commands/
3
+ *
4
+ * Copies command templates from the installed package into the user's
5
+ * .claude/commands/ directory. Existing files can be overwritten with --force.
6
+ *
7
+ * Zero npm dependencies.
8
+ */
9
+
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ import { fileURLToPath } from 'url';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+
17
+ function packageRoot() {
18
+ return path.resolve(__dirname, '..');
19
+ }
20
+
21
+ export async function run(dir, args) {
22
+ const force = args.includes('--force');
23
+ const srcDir = path.join(packageRoot(), 'templates', 'commands');
24
+ const destDir = path.join(dir, '.claude', 'commands');
25
+
26
+ fs.mkdirSync(destDir, { recursive: true });
27
+
28
+ let files;
29
+ try {
30
+ files = fs.readdirSync(srcDir).filter(f => f.endsWith('.md'));
31
+ } catch (err) {
32
+ console.error(`Cannot read command templates: ${err.message}`);
33
+ process.exit(1);
34
+ }
35
+
36
+ console.log();
37
+ console.log(` Updating .claude/commands/ (${files.length} commands)`);
38
+ console.log();
39
+
40
+ let updated = 0;
41
+ let skipped = 0;
42
+
43
+ for (const file of files) {
44
+ const src = path.join(srcDir, file);
45
+ const dest = path.join(destDir, file);
46
+
47
+ if (fs.existsSync(dest) && !force) {
48
+ // Check if content differs
49
+ const srcContent = fs.readFileSync(src, 'utf8');
50
+ const destContent = fs.readFileSync(dest, 'utf8');
51
+ if (srcContent !== destContent) {
52
+ console.log(` \x1b[33m~\x1b[0m ${file} (differs, use --force to overwrite)`);
53
+ skipped++;
54
+ } else {
55
+ console.log(` \x1b[2m= ${file} (up to date)\x1b[0m`);
56
+ }
57
+ continue;
58
+ }
59
+
60
+ fs.copyFileSync(src, dest);
61
+ console.log(` \x1b[32m+\x1b[0m ${file}`);
62
+ updated++;
63
+ }
64
+
65
+ console.log();
66
+ console.log(` ${updated} updated, ${skipped} skipped`);
67
+ if (skipped > 0 && !force) {
68
+ console.log(' Run "wheat update --force" to overwrite all');
69
+ }
70
+ console.log();
71
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@grainulation/wheat",
3
+ "version": "1.0.0",
4
+ "description": "Research-driven development framework — structured claims, compiled evidence, deterministic output",
5
+ "license": "MIT",
6
+ "author": "grainulation contributors",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/grainulation/wheat.git"
10
+ },
11
+ "homepage": "https://wheat.grainulation.com",
12
+ "bugs": {
13
+ "url": "https://github.com/grainulation/wheat/issues"
14
+ },
15
+ "keywords": [
16
+ "wheat-framework",
17
+ "research-sprint",
18
+ "claims-compiler",
19
+ "claude-code",
20
+ "structured-research",
21
+ "evidence-graded",
22
+ "decision-framework",
23
+ "research-driven-development",
24
+ "developer-research",
25
+ "technical-decision-making"
26
+ ],
27
+ "type": "module",
28
+ "main": "./lib/index.js",
29
+ "exports": {
30
+ ".": "./lib/index.js",
31
+ "./compiler": "./lib/compiler.js",
32
+ "./server": "./lib/server.js",
33
+ "./guard": "./lib/guard.js",
34
+ "./connect": "./lib/connect.js",
35
+ "./mcp": "./lib/serve-mcp.js"
36
+ },
37
+ "bin": {
38
+ "wheat": "bin/wheat.js"
39
+ },
40
+ "files": [
41
+ "bin/",
42
+ "lib/",
43
+ "public/",
44
+ "compiler/",
45
+ "templates/"
46
+ ],
47
+ "scripts": {
48
+ "test": "node --test test/cli.test.js test/compiler.test.js test/guard.test.js test/init.test.js"
49
+ },
50
+ "engines": {
51
+ "node": ">=18"
52
+ }
53
+ }