@grainulation/orchard 1.0.0 → 1.0.2

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/lib/sync.js CHANGED
@@ -1,8 +1,8 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
- const fs = require('node:fs');
4
- const path = require('node:path');
5
- const { readSprintState } = require('./tracker.js');
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const { readSprintState } = require("./tracker.js");
6
6
 
7
7
  /**
8
8
  * Sync all sprint states from their directories into orchard.json.
@@ -12,9 +12,9 @@ function syncAll(config, root) {
12
12
  const sprints = config.sprints || [];
13
13
  let updated = 0;
14
14
 
15
- console.log('');
16
- console.log(' Syncing sprint states...');
17
- console.log('');
15
+ console.log("");
16
+ console.log(" Syncing sprint states...");
17
+ console.log("");
18
18
 
19
19
  for (const sprint of sprints) {
20
20
  const state = readSprintState(sprint.path, root);
@@ -30,25 +30,29 @@ function syncAll(config, root) {
30
30
  if (oldStatus !== inferred) {
31
31
  sprint.status = inferred;
32
32
  updated++;
33
- console.log(` [~] ${path.basename(sprint.path)}: ${oldStatus || 'unknown'} -> ${inferred}`);
33
+ console.log(
34
+ ` [~] ${path.basename(sprint.path)}: ${oldStatus || "unknown"} -> ${inferred}`,
35
+ );
34
36
  } else {
35
- console.log(` [=] ${path.basename(sprint.path)}: ${inferred} (${state.claimsCount} claims)`);
37
+ console.log(
38
+ ` [=] ${path.basename(sprint.path)}: ${inferred} (${state.claimsCount} claims)`,
39
+ );
36
40
  }
37
41
  }
38
42
 
39
43
  if (updated > 0) {
40
- const configPath = path.join(root, 'orchard.json');
41
- const tmp = configPath + '.tmp.' + process.pid;
42
- fs.writeFileSync(tmp, JSON.stringify(config, null, 2) + '\n');
44
+ const configPath = path.join(root, "orchard.json");
45
+ const tmp = configPath + ".tmp." + process.pid;
46
+ fs.writeFileSync(tmp, JSON.stringify(config, null, 2) + "\n");
43
47
  fs.renameSync(tmp, configPath);
44
- console.log('');
48
+ console.log("");
45
49
  console.log(` Updated ${updated} sprint(s) in orchard.json.`);
46
50
  } else {
47
- console.log('');
48
- console.log(' All sprints up to date.');
51
+ console.log("");
52
+ console.log(" All sprints up to date.");
49
53
  }
50
54
 
51
- console.log('');
55
+ console.log("");
52
56
  }
53
57
 
54
58
  /**
@@ -56,15 +60,15 @@ function syncAll(config, root) {
56
60
  */
57
61
  function inferStatus(sprint, state) {
58
62
  // If manually set to done, keep it
59
- if (sprint.status === 'done') return 'done';
63
+ if (sprint.status === "done") return "done";
60
64
 
61
65
  // If manually blocked, keep it
62
- if (sprint.status === 'blocked') return 'blocked';
66
+ if (sprint.status === "blocked") return "blocked";
63
67
 
64
- if (!state.exists) return 'not-found';
65
- if (state.claimsCount === 0) return 'not-started';
66
- if (state.hasCompilation) return 'compiled';
67
- return 'active';
68
+ if (!state.exists) return "not-found";
69
+ if (state.claimsCount === 0) return "not-started";
70
+ if (state.hasCompilation) return "compiled";
71
+ return "active";
68
72
  }
69
73
 
70
74
  /**
@@ -75,15 +79,17 @@ function findReady(config, root) {
75
79
  const statuses = new Map();
76
80
 
77
81
  for (const s of sprints) {
78
- statuses.set(s.path, s.status || 'unknown');
82
+ statuses.set(s.path, s.status || "unknown");
79
83
  }
80
84
 
81
85
  const ready = [];
82
86
  for (const s of sprints) {
83
- if (s.status === 'done' || s.status === 'active') continue;
87
+ if (s.status === "done" || s.status === "active") continue;
84
88
 
85
89
  const deps = s.depends_on || [];
86
- const allDone = deps.every((d) => statuses.get(d) === 'done' || statuses.get(d) === 'compiled');
90
+ const allDone = deps.every(
91
+ (d) => statuses.get(d) === "done" || statuses.get(d) === "compiled",
92
+ );
87
93
 
88
94
  if (allDone) {
89
95
  ready.push(s);
package/lib/tracker.js CHANGED
@@ -1,31 +1,36 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
- const fs = require('node:fs');
4
- const path = require('node:path');
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
5
 
6
6
  /**
7
7
  * Read sprint status from its directory.
8
8
  * Looks for claims.json and compilation.json to determine state.
9
9
  */
10
10
  function readSprintState(sprintPath, root) {
11
- const absPath = path.isAbsolute(sprintPath) ? sprintPath : path.join(root, sprintPath);
11
+ const absPath = path.isAbsolute(sprintPath)
12
+ ? sprintPath
13
+ : path.join(root, sprintPath);
12
14
  const state = {
13
15
  exists: false,
14
16
  claimsCount: 0,
15
17
  hasCompilation: false,
16
18
  lastModified: null,
17
- status: 'unknown',
19
+ status: "unknown",
18
20
  };
19
21
 
20
22
  if (!fs.existsSync(absPath)) return state;
21
23
  state.exists = true;
22
24
 
23
- const claimsPath = path.join(absPath, 'claims.json');
25
+ const claimsPath = path.join(absPath, "claims.json");
24
26
  if (fs.existsSync(claimsPath)) {
25
27
  try {
26
- const claims = JSON.parse(fs.readFileSync(claimsPath, 'utf8'));
27
- state.claimsCount = Array.isArray(claims) ? claims.length :
28
- (claims.claims ? claims.claims.length : 0);
28
+ const claims = JSON.parse(fs.readFileSync(claimsPath, "utf8"));
29
+ state.claimsCount = Array.isArray(claims)
30
+ ? claims.length
31
+ : claims.claims
32
+ ? claims.claims.length
33
+ : 0;
29
34
  const stat = fs.statSync(claimsPath);
30
35
  state.lastModified = stat.mtime;
31
36
  } catch {
@@ -33,16 +38,16 @@ function readSprintState(sprintPath, root) {
33
38
  }
34
39
  }
35
40
 
36
- const compilationPath = path.join(absPath, 'compilation.json');
41
+ const compilationPath = path.join(absPath, "compilation.json");
37
42
  state.hasCompilation = fs.existsSync(compilationPath);
38
43
 
39
44
  // Infer status
40
45
  if (state.claimsCount === 0) {
41
- state.status = 'not-started';
46
+ state.status = "not-started";
42
47
  } else if (state.hasCompilation) {
43
- state.status = 'compiled';
48
+ state.status = "compiled";
44
49
  } else {
45
- state.status = 'in-progress';
50
+ state.status = "in-progress";
46
51
  }
47
52
 
48
53
  return state;
@@ -55,52 +60,59 @@ function printStatus(config, root) {
55
60
  const sprints = config.sprints || [];
56
61
 
57
62
  if (sprints.length === 0) {
58
- console.log('No sprints configured. Add sprints to orchard.json.');
63
+ console.log("No sprints configured. Add sprints to orchard.json.");
59
64
  return;
60
65
  }
61
66
 
62
- const active = sprints.filter((s) => s.status === 'active' || !s.status).length;
63
- const done = sprints.filter((s) => s.status === 'done').length;
67
+ const active = sprints.filter(
68
+ (s) => s.status === "active" || !s.status,
69
+ ).length;
70
+ const done = sprints.filter((s) => s.status === "done").length;
64
71
 
65
- console.log('');
66
- console.log(` ${sprints.length} sprints tracked. ${active} active, ${done} done.`);
67
- console.log(' ' + '-'.repeat(70));
72
+ console.log("");
68
73
  console.log(
69
- ' ' +
70
- 'Sprint'.padEnd(20) +
71
- 'Status'.padEnd(14) +
72
- 'Claims'.padEnd(10) +
73
- 'Assigned'.padEnd(16) +
74
- 'Deadline'
74
+ ` ${sprints.length} sprints tracked. ${active} active, ${done} done.`,
75
75
  );
76
- console.log(' ' + '-'.repeat(70));
76
+ console.log(" " + "-".repeat(70));
77
+ console.log(
78
+ " " +
79
+ "Sprint".padEnd(20) +
80
+ "Status".padEnd(14) +
81
+ "Claims".padEnd(10) +
82
+ "Assigned".padEnd(16) +
83
+ "Deadline",
84
+ );
85
+ console.log(" " + "-".repeat(70));
77
86
 
78
87
  for (const sprint of sprints) {
79
88
  const state = readSprintState(sprint.path, root);
80
89
  const name = path.basename(sprint.path).substring(0, 18);
81
90
  const status = sprint.status || state.status;
82
91
  const claims = state.claimsCount.toString();
83
- const assignee = (sprint.assigned_to || '-').substring(0, 14);
84
- const deadline = sprint.deadline || '-';
92
+ const assignee = (sprint.assigned_to || "-").substring(0, 14);
93
+ const deadline = sprint.deadline || "-";
85
94
 
86
95
  const statusDisplay =
87
- status === 'active' ? '* active' :
88
- status === 'done' ? 'x done' :
89
- status === 'blocked' ? '! blocked' :
90
- ` ${status}`;
96
+ status === "active"
97
+ ? "* active"
98
+ : status === "done"
99
+ ? "x done"
100
+ : status === "blocked"
101
+ ? "! blocked"
102
+ : ` ${status}`;
91
103
 
92
104
  console.log(
93
- ' ' +
94
- name.padEnd(20) +
95
- statusDisplay.padEnd(14) +
96
- claims.padEnd(10) +
97
- assignee.padEnd(16) +
98
- deadline
105
+ " " +
106
+ name.padEnd(20) +
107
+ statusDisplay.padEnd(14) +
108
+ claims.padEnd(10) +
109
+ assignee.padEnd(16) +
110
+ deadline,
99
111
  );
100
112
  }
101
113
 
102
- console.log(' ' + '-'.repeat(70));
103
- console.log('');
114
+ console.log(" " + "-".repeat(70));
115
+ console.log("");
104
116
  }
105
117
 
106
118
  /**
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@grainulation/orchard",
3
- "version": "1.0.0",
4
- "description": "Multi-sprint research orchestrator \u2014 coordinate parallel research across teams",
3
+ "version": "1.0.2",
4
+ "description": "Multi-sprint research orchestrator coordinate parallel research across teams",
5
5
  "main": "lib/planner.js",
6
6
  "exports": {
7
7
  ".": "./lib/planner.js",
8
8
  "./server": "./lib/server.js",
9
9
  "./sync": "./lib/sync.js",
10
10
  "./tracker": "./lib/tracker.js",
11
+ "./conflicts": "./lib/conflicts.js",
12
+ "./hackathon": "./lib/hackathon.js",
13
+ "./decompose": "./lib/decompose.js",
11
14
  "./doctor": "./lib/doctor.js",
12
15
  "./package.json": "./package.json"
13
16
  },
@@ -20,7 +23,9 @@
20
23
  "public/",
21
24
  "templates/",
22
25
  "README.md",
23
- "LICENSE"
26
+ "LICENSE",
27
+ "CODE_OF_CONDUCT.md",
28
+ "CONTRIBUTING.md"
24
29
  ],
25
30
  "scripts": {
26
31
  "test": "node test/basic.test.js",
@@ -36,6 +41,7 @@
36
41
  ],
37
42
  "author": "grainulation contributors",
38
43
  "license": "MIT",
44
+ "type": "module",
39
45
  "repository": {
40
46
  "type": "git",
41
47
  "url": "git+https://github.com/grainulation/orchard.git"
@@ -45,6 +51,6 @@
45
51
  },
46
52
  "homepage": "https://orchard.grainulation.com",
47
53
  "engines": {
48
- "node": ">=18"
54
+ "node": ">=20"
49
55
  }
50
56
  }