@grainulation/harvest 1.0.0 → 1.0.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,25 @@
1
+ # Code of Conduct
2
+
3
+ ## Our standards
4
+
5
+ We are committed to providing a welcoming and productive environment for everyone. We expect participants to:
6
+
7
+ - Use welcoming and inclusive language
8
+ - Respect differing viewpoints and experiences
9
+ - Accept constructive criticism gracefully
10
+ - Focus on what is best for the community and the project
11
+ - Show empathy toward other participants
12
+
13
+ Unacceptable behavior includes harassment, trolling, personal attacks, and publishing others' private information without permission.
14
+
15
+ ## Scope
16
+
17
+ This code of conduct applies to all project spaces -- issues, pull requests, discussions, and any public channel where someone represents the project.
18
+
19
+ ## Enforcement
20
+
21
+ Instances of unacceptable behavior may be reported to the project maintainers. All complaints will be reviewed and investigated, and will result in a response deemed necessary and appropriate.
22
+
23
+ ## Attribution
24
+
25
+ Adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
@@ -0,0 +1,87 @@
1
+ # Contributing to Harvest
2
+
3
+ Thanks for considering contributing. Harvest is the retrospective and analytics engine for the grainulation ecosystem -- it turns sprint history into insights and calibration data.
4
+
5
+ ## Quick setup
6
+
7
+ ```bash
8
+ git clone https://github.com/grainulation/harvest.git
9
+ cd harvest
10
+ node bin/harvest.js --help
11
+ ```
12
+
13
+ No `npm install` needed -- harvest has zero dependencies.
14
+
15
+ ## How to contribute
16
+
17
+ ### Report a bug
18
+ Open an issue with:
19
+ - What you expected
20
+ - What happened instead
21
+ - Your Node version (`node --version`)
22
+ - Steps to reproduce
23
+
24
+ ### Suggest a feature
25
+ Open an issue describing the use case, not just the solution. "I need X because Y" is more useful than "add X."
26
+
27
+ ### Submit a PR
28
+ 1. Fork the repo
29
+ 2. Create a branch (`git checkout -b fix/description`)
30
+ 3. Make your changes
31
+ 4. Run the tests: `node --test test/basic.test.js`
32
+ 5. Commit with a clear message
33
+ 6. Open a PR
34
+
35
+ ## Architecture
36
+
37
+ ```
38
+ bin/harvest.js CLI entrypoint -- dispatches subcommands
39
+ lib/analyzer.js Sprint data analysis and pattern detection
40
+ lib/calibration.js Prediction vs outcome scoring
41
+ lib/decay.js Claim staleness and evidence decay
42
+ lib/patterns.js Recurring pattern extraction
43
+ lib/report.js Report generation from analyzed data
44
+ lib/server.js Local preview server (SSE, zero deps)
45
+ lib/templates.js Template rendering for HTML output
46
+ lib/velocity.js Sprint velocity tracking
47
+ templates/ HTML templates (retrospective, etc.)
48
+ public/ Web UI -- retrospective dashboard
49
+ site/ Public website (harvest.grainulation.com)
50
+ test/ Node built-in test runner tests
51
+ ```
52
+
53
+ The key architectural principle: **harvest reads sprint artifacts (claims, compilations, git history) and produces calibrated insights.** It never modifies source data -- read-only analysis, write-only reports.
54
+
55
+ ## Code style
56
+
57
+ - Zero dependencies. If you need something, write it or use Node built-ins.
58
+ - No transpilation. Ship what you write.
59
+ - ESM imports (`import`/`export`). Node 18+ required.
60
+ - Keep functions small. If a function needs a scroll, split it.
61
+ - No emojis in code, CLI output, or reports.
62
+
63
+ ## Testing
64
+
65
+ ```bash
66
+ node --test test/basic.test.js
67
+ ```
68
+
69
+ Tests use Node's built-in test runner. No test framework dependencies.
70
+
71
+ ## Commit messages
72
+
73
+ Follow the existing pattern:
74
+ ```
75
+ harvest: <what changed>
76
+ ```
77
+
78
+ Examples:
79
+ ```
80
+ harvest: add velocity trend chart
81
+ harvest: fix decay calculation for stale claims
82
+ harvest: update calibration scoring algorithm
83
+ ```
84
+
85
+ ## License
86
+
87
+ MIT. See LICENSE for details.
package/README.md CHANGED
@@ -1,10 +1,26 @@
1
- # @grainulation/harvest
1
+ <p align="center">
2
+ <img src="site/wordmark.svg" alt="Harvest" width="400">
3
+ </p>
2
4
 
3
- **Are your decisions getting better?**
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/@grainulation/harvest"><img src="https://img.shields.io/npm/v/@grainulation/harvest" alt="npm version"></a> <a href="https://www.npmjs.com/package/@grainulation/harvest"><img src="https://img.shields.io/npm/dm/@grainulation/harvest" alt="npm downloads"></a> <a href="https://github.com/grainulation/harvest/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@grainulation/harvest" alt="license"></a> <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/@grainulation/harvest" alt="node"></a> <a href="https://github.com/grainulation/harvest/actions"><img src="https://github.com/grainulation/harvest/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
7
+ </p>
4
8
 
5
- Harvest is the analytics and retrospective layer for research sprints. It looks across sprints to find patterns, score predictions, and surface knowledge that's gone stale.
9
+ <p align="center"><strong>Are your decisions getting better?</strong></p>
6
10
 
7
- Learn from every decision you've made.
11
+ Harvest is the analytics layer for research sprints. It looks across sprints to find patterns, score predictions, and surface knowledge that's gone stale.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install -g @grainulation/harvest
17
+ ```
18
+
19
+ Or use directly:
20
+
21
+ ```bash
22
+ npx @grainulation/harvest analyze ./sprints/
23
+ ```
8
24
 
9
25
  ## What it does
10
26
 
@@ -15,21 +31,9 @@ Learn from every decision you've made.
15
31
  - **Sprint velocity** -- how long do sprints take, where do they stall?
16
32
  - **Retrospective reports** -- dark-themed HTML reports for the team
17
33
 
18
- ## Install
19
-
20
- ```sh
21
- npm install @grainulation/harvest
22
- ```
34
+ ## Quick start
23
35
 
24
- Or run directly:
25
-
26
- ```sh
27
- npx @grainulation/harvest analyze ./sprints/
28
- ```
29
-
30
- ## Usage
31
-
32
- ```sh
36
+ ```bash
33
37
  # Cross-sprint claim analysis
34
38
  harvest analyze ./sprints/
35
39
 
@@ -50,52 +54,46 @@ harvest report ./sprints/ -o retrospective.html
50
54
 
51
55
  # All analyses in one pass
52
56
  harvest trends ./sprints/ --json
57
+
58
+ # Start the live dashboard (SSE updates, dark theme)
59
+ harvest serve --root ./sprints/ --port 9096
60
+
61
+ # Connect to farmer for mobile monitoring
62
+ harvest connect farmer --url http://localhost:9094
53
63
  ```
54
64
 
55
65
  ## Data format
56
66
 
57
67
  Harvest reads standard wheat sprint data:
58
68
 
59
- - `claims.json` -- array of typed claims with `id`, `type`, `evidence`, `status`, `text`, `created`, etc.
69
+ - `claims.json` -- array of typed claims with `id`, `type`, `evidence`, `status`, `text`, `created`
60
70
  - `compilation.json` -- compiled sprint state (optional, enriches analysis)
61
71
  - Git history on `claims.json` -- used for velocity and timing analysis
62
72
 
63
- Point harvest at a directory containing sprint subdirectories, or at a single sprint directory:
64
-
65
- ```
66
- sprints/
67
- sprint-alpha/
68
- claims.json
69
- compilation.json
70
- sprint-beta/
71
- claims.json
72
- ```
73
+ Point harvest at a directory containing sprint subdirectories, or at a single sprint directory.
73
74
 
74
75
  ## Design
75
76
 
76
- - **Zero dependencies** -- Node built-in modules only (fs, path, child_process)
77
77
  - **Reads, never writes** -- harvest is a pure analysis tool; it won't modify your sprint data
78
78
  - **Git-aware** -- uses git log timestamps for velocity analysis when available
79
79
  - **Composable** -- each module (analyzer, calibration, patterns, decay, velocity) works independently
80
80
 
81
- ## Claim types it understands
81
+ ## Zero dependencies
82
82
 
83
- | Type | What it means |
84
- |---|---|
85
- | `constraint` | Hard requirements, non-negotiable |
86
- | `factual` | Verifiable statements |
87
- | `estimate` | Predictions, projections, ranges |
88
- | `risk` | Potential failure modes |
89
- | `recommendation` | Proposed courses of action |
90
- | `feedback` | Stakeholder input |
83
+ Node built-in modules only.
91
84
 
92
- ## Evidence tiers (lowest to highest)
85
+ ## Part of the grainulation ecosystem
93
86
 
94
- 1. `stated` -- someone said it
95
- 2. `web` -- found online
96
- 3. `documented` -- in source code or official docs
97
- 4. `tested` -- verified via prototype or benchmark
98
- 5. `production` -- measured from live systems
87
+ | Tool | Role |
88
+ |------|------|
89
+ | [wheat](https://github.com/grainulation/wheat) | Research engine -- grow structured evidence |
90
+ | [farmer](https://github.com/grainulation/farmer) | Permission dashboard -- approve AI actions in real time |
91
+ | [barn](https://github.com/grainulation/barn) | Shared tools -- templates, validators, sprint detection |
92
+ | [mill](https://github.com/grainulation/mill) | Format conversion -- export to PDF, CSV, slides, 24 formats |
93
+ | [silo](https://github.com/grainulation/silo) | Knowledge storage -- reusable claim libraries and packs |
94
+ | **harvest** | Analytics -- cross-sprint patterns and prediction scoring |
95
+ | [orchard](https://github.com/grainulation/orchard) | Orchestration -- multi-sprint coordination and dependencies |
96
+ | [grainulation](https://github.com/grainulation/grainulation) | Unified CLI -- single entry point to the ecosystem |
99
97
 
100
98
  ## License
101
99
 
package/lib/server.js CHANGED
@@ -81,7 +81,7 @@ const { analyze } = require('./analyzer.js');
81
81
  const { measureVelocity } = require('./velocity.js');
82
82
  const { checkDecay } = require('./decay.js');
83
83
  const { calibrate } = require('./calibration.js');
84
- const { loadSprints: loadDashboardSprints, buildHtml, claimsPaths } = require('./dashboard.js');
84
+ const { claimsPaths } = require('./dashboard.js');
85
85
 
86
86
  // ── Sprint discovery ─────────────────────────────────────────────────────────
87
87
 
@@ -204,38 +204,6 @@ function jsonResponse(res, code, data) {
204
204
  res.end(JSON.stringify(data));
205
205
  }
206
206
 
207
- // ── SSE live-reload injection ────────────────────────────────────────────────
208
-
209
- const SSE_SCRIPT = `
210
- <script>
211
- (function() {
212
- var es, retryCount = 0;
213
- var dot = document.getElementById('statusDot');
214
- function connect() {
215
- es = new EventSource('/events');
216
- es.addEventListener('update', function() { location.reload(); });
217
- es.onopen = function() {
218
- retryCount = 0;
219
- if (dot) dot.className = 'status-dot ok';
220
- if (window._grainSetState) window._grainSetState('idle');
221
- };
222
- es.onerror = function() {
223
- es.close();
224
- if (dot) dot.className = 'status-dot';
225
- if (window._grainSetState) window._grainSetState('orbit');
226
- var delay = Math.min(30000, 1000 * Math.pow(2, retryCount)) + Math.random() * 1000;
227
- retryCount++;
228
- setTimeout(connect, delay);
229
- };
230
- }
231
- connect();
232
- })();
233
- </script>`;
234
-
235
- function injectSSE(html) {
236
- return html.replace('</body>', SSE_SCRIPT + '\n</body>');
237
- }
238
-
239
207
  // ── HTTP server ───────────────────────────────────────────────────────────────
240
208
 
241
209
  const server = createServer(async (req, res) => {
@@ -375,21 +343,16 @@ ${ROUTES.map(r => '<tr><td><code>'+r.method+'</code></td><td><code>'+r.path+'</c
375
343
  return;
376
344
  }
377
345
 
378
- // ── Dashboard UI (template-injected) ──
346
+ // ── Dashboard UI (web app from public/) ──
379
347
  if (req.method === 'GET' && (url.pathname === '/' || url.pathname === '/index.html')) {
348
+ const indexPath = join(PUBLIC_DIR, 'index.html');
380
349
  try {
381
- const sprints = loadDashboardSprints(ROOT);
382
- if (sprints.length === 0) {
383
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
384
- res.end('<html><body style="background:#0a0e1a;color:#e2e8f0;font-family:monospace;padding:40px"><h1>No claims.json files found</h1><p>Watching for changes...</p>' + SSE_SCRIPT + '</body></html>');
385
- return;
386
- }
387
- const html = injectSSE(buildHtml(sprints));
350
+ const html = readFileSync(indexPath, 'utf8');
388
351
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
389
352
  res.end(html);
390
353
  } catch (err) {
391
354
  res.writeHead(500, { 'Content-Type': 'text/plain' });
392
- res.end('Error building dashboard: ' + err.message);
355
+ res.end('Error reading dashboard: ' + err.message);
393
356
  }
394
357
  return;
395
358
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grainulation/harvest",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Analytics and retrospective layer for research sprints -- learn from every decision you've made",
5
5
  "main": "lib/analyzer.js",
6
6
  "exports": {
@@ -35,7 +35,9 @@
35
35
  "public/",
36
36
  "templates/",
37
37
  "README.md",
38
- "LICENSE"
38
+ "LICENSE",
39
+ "CODE_OF_CONDUCT.md",
40
+ "CONTRIBUTING.md"
39
41
  ],
40
42
  "engines": {
41
43
  "node": ">=18.0.0"