@stylusnexus/work-plan 2026.6.15-2 → 2026.6.15-3
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/README.md
CHANGED
|
@@ -280,7 +280,7 @@ A skill has two distinct contracts: (1) the underlying **CLI** that does the wor
|
|
|
280
280
|
|
|
281
281
|
| Tool | Install command | Then invoke as |
|
|
282
282
|
|---|---|---|
|
|
283
|
-
| **npm (standalone CLI / any editor)** | `npm install -g @stylusnexus/work-plan` (requires `python3` + `yq` + `gh` already on PATH — the
|
|
283
|
+
| **npm (standalone CLI / any editor)** | `npm install -g @stylusnexus/work-plan` (requires `python3` + `yq` + `gh` already on PATH — the CLI warns on first run if any are missing). | `work-plan <subcommand>` |
|
|
284
284
|
| **Claude Code** | **Plugin (recommended):** `/plugin marketplace add stylusnexus/agent-plugins` → `/plugin install work-plan@stylus-nexus`. Or script: `./install.sh` / `.\install.ps1` | Plugin: `/work-plan:brief` … `/work-plan:run <sub>`. Script: bare `/work-plan <subcommand>` |
|
|
285
285
|
| **Codex** | **Plugin:** `codex plugin marketplace add stylusnexus/agent-plugins` → `codex plugin add work-plan@stylus-nexus`. Or script: `./install.sh --target=$HOME/.agents` | Plugin: `@work-plan` / `/skills`. Script: direct CLI |
|
|
286
286
|
| **Cursor** | Skip installer. Clone repo + copy `shims/cursor/work-plan.cursorrules` into your project's `.cursorrules` (or merge it in) | `python3 <toolkit>/skills/work-plan/work_plan.py <sub>` — alias `wp` recommended |
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2026.06.15+
|
|
1
|
+
2026.06.15+e3f3cdf
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stylusnexus/work-plan",
|
|
3
|
-
"version": "2026.6.15-
|
|
3
|
+
"version": "2026.6.15-3",
|
|
4
4
|
"description": "Track-aware daily work planning over GitHub issues. Shared tracks (git-synced .work-plan/ in each repo), AI clustering (group/auto-triage), VS Code viewer, Claude Code + Codex plugins. Pure Python stdlib.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"work-plan": "bin/work-plan"
|
|
@@ -8,14 +8,10 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
10
|
"skills/work-plan/",
|
|
11
|
-
"scripts/npm-check-deps.js",
|
|
12
11
|
"VERSION",
|
|
13
12
|
"LICENSE",
|
|
14
13
|
"README.md"
|
|
15
14
|
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"postinstall": "node scripts/npm-check-deps.js"
|
|
18
|
-
},
|
|
19
15
|
"engines": {
|
|
20
16
|
"node": ">=18"
|
|
21
17
|
},
|
|
@@ -93,11 +93,19 @@ def run(args: list[str]) -> int:
|
|
|
93
93
|
visibility[t.repo] = repo_visibility(t.repo)
|
|
94
94
|
|
|
95
95
|
# Compute untracked: open issues not referenced by any track, per repo.
|
|
96
|
+
# Iterate over every repo that has ANY track — NOT just repos in
|
|
97
|
+
# repo_to_numbers (which only collects tracks whose github.issues is
|
|
98
|
+
# non-empty). A repo whose only track has `issues: []` must still get its
|
|
99
|
+
# open issues surfaced as untracked; otherwise creating an empty track in a
|
|
100
|
+
# previously-trackless repo makes its open issues vanish — neither in the
|
|
101
|
+
# (empty) track nor in untracked, and the viewer's trackless fallback
|
|
102
|
+
# (treeModel.mergeFetchedUntracked) shuts off the moment a track exists (#342).
|
|
96
103
|
# One `gh issue list` call per repo — bounded by the number of tracked repos
|
|
97
104
|
# (typically a handful), not by issue count, so a serial loop is fine.
|
|
105
|
+
tracked_repos = {t.repo for t in tracks if t.repo}
|
|
98
106
|
untracked_by_repo: dict[str, list] = {}
|
|
99
|
-
for repo in
|
|
100
|
-
tracked = set(repo_to_numbers[
|
|
107
|
+
for repo in tracked_repos:
|
|
108
|
+
tracked = set(repo_to_numbers.get(repo, []))
|
|
101
109
|
open_rows = fetch_open_issues(repo)
|
|
102
110
|
untracked_by_repo[repo] = [r for r in open_rows if r.get("number") not in tracked]
|
|
103
111
|
|
|
@@ -290,6 +290,19 @@ class ExportCommandUntrackedTest(unittest.TestCase):
|
|
|
290
290
|
self.assertEqual(rc, 0)
|
|
291
291
|
self.assertEqual(out["untracked"], [])
|
|
292
292
|
|
|
293
|
+
def test_empty_track_still_surfaces_untracked(self):
|
|
294
|
+
"""A repo whose only track has issues:[] must still surface its open
|
|
295
|
+
issues as untracked (#342). repo_to_numbers omits such a track, so the
|
|
296
|
+
untracked loop must key off repos-with-tracks, not tracked issues."""
|
|
297
|
+
tracks = [_track("general", _SHARED_REPO, [])] # empty track
|
|
298
|
+
export_map = {} # no tracked issues to fetch
|
|
299
|
+
open_rows = {_SHARED_REPO: [_ISSUE_A, _ISSUE_C]} # but the repo has open issues
|
|
300
|
+
rc, out = self._run_with_mocks(tracks, export_map, open_rows)
|
|
301
|
+
self.assertEqual(rc, 0)
|
|
302
|
+
entry = next(e for e in out["untracked"] if e["repo"] == _SHARED_REPO)
|
|
303
|
+
nums = sorted(i["number"] for i in entry["issues"])
|
|
304
|
+
self.assertEqual(nums, [1, 3]) # both open issues are untracked
|
|
305
|
+
|
|
293
306
|
def test_schema_stays_1_with_untracked(self):
|
|
294
307
|
tracks = [_track("alpha", _SHARED_REPO, [1])]
|
|
295
308
|
open_rows = {_SHARED_REPO: [_ISSUE_A, _ISSUE_B]}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Postinstall check for the @stylusnexus/work-plan npm package.
|
|
3
|
-
//
|
|
4
|
-
// The work-plan CLI is pure Python and shells out to three external tools at
|
|
5
|
-
// runtime. npm can't install them (they're not npm packages), so we just check
|
|
6
|
-
// they're on PATH and print a friendly heads-up if any are missing. This NEVER
|
|
7
|
-
// fails the install — a missing tool is the user's to fix, and the CLI prints
|
|
8
|
-
// its own clear error if one is absent when actually run.
|
|
9
|
-
|
|
10
|
-
const { execSync } = require("node:child_process");
|
|
11
|
-
|
|
12
|
-
const TOOLS = [
|
|
13
|
-
{ cmd: "python3", why: "runs the CLI", hint: "https://www.python.org/downloads/ (or `brew install python`)" },
|
|
14
|
-
{ cmd: "yq", why: "parses config + frontmatter (mikefarah/yq, the Go one — NOT the python yq)", hint: "brew install yq · https://github.com/mikefarah/yq" },
|
|
15
|
-
{ cmd: "gh", why: "reads GitHub issue state", hint: "brew install gh · https://cli.github.com" },
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
function have(cmd) {
|
|
19
|
-
try {
|
|
20
|
-
const probe = process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`;
|
|
21
|
-
execSync(probe, { stdio: "ignore", shell: true });
|
|
22
|
-
return true;
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
const missing = TOOLS.filter((t) => !have(t.cmd));
|
|
30
|
-
if (missing.length) {
|
|
31
|
-
const lines = [
|
|
32
|
-
"",
|
|
33
|
-
" work-plan installed. It needs a few tools on your PATH that npm can't install:",
|
|
34
|
-
...missing.map((t) => ` • ${t.cmd} — ${t.why}\n ${t.hint}`),
|
|
35
|
-
"",
|
|
36
|
-
" (The CLI will tell you specifically if one is missing when you run it.)",
|
|
37
|
-
"",
|
|
38
|
-
];
|
|
39
|
-
console.warn(lines.join("\n"));
|
|
40
|
-
}
|
|
41
|
-
} catch {
|
|
42
|
-
// Never let the check itself break the install.
|
|
43
|
-
}
|
|
44
|
-
process.exit(0);
|