chief-clancy 0.3.8 → 0.3.9

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Autonomous, board-driven development for Claude Code.**
4
4
 
5
- [![npm](https://img.shields.io/npm/v/chief-clancy?style=for-the-badge&color=cb3837)](https://www.npmjs.com/package/chief-clancy) [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](./LICENSE) [![Tests](https://img.shields.io/badge/tests-146%20passing-brightgreen?style=for-the-badge)](docs/TESTING.md) [![GitHub Stars](https://img.shields.io/github/stars/Pushedskydiver/clancy?style=for-the-badge)](https://github.com/Pushedskydiver/clancy/stargazers)
5
+ [![npm](https://img.shields.io/npm/v/chief-clancy?style=for-the-badge&color=cb3837)](https://www.npmjs.com/package/chief-clancy) [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](./LICENSE) [![Tests](https://img.shields.io/badge/tests-161%20passing-brightgreen?style=for-the-badge)](docs/TESTING.md) [![GitHub Stars](https://img.shields.io/github/stars/Pushedskydiver/clancy?style=for-the-badge)](https://github.com/Pushedskydiver/clancy/stargazers)
6
6
 
7
7
  > [!WARNING]
8
8
  > Clancy is in early development. Expect bugs, breaking changes, and rough edges. If you hit an issue, please [open a bug report](https://github.com/Pushedskydiver/clancy/issues/new).
@@ -1,101 +1,2 @@
1
- // dist/scripts/afk/afk.js
2
- import { spawnSync } from "node:child_process";
3
- import { existsSync } from "node:fs";
4
- import { dirname, join, resolve } from "node:path";
5
- import { setTimeout as sleep } from "node:timers/promises";
6
- import { fileURLToPath } from "node:url";
7
-
8
- // dist/utils/ansi/ansi.js
9
- var dim = (s) => `\x1B[2m${s}\x1B[0m`;
10
- var bold = (s) => `\x1B[1m${s}\x1B[0m`;
11
- var green = (s) => `\x1B[32m${s}\x1B[0m`;
12
- var red = (s) => `\x1B[31m${s}\x1B[0m`;
13
-
14
- // dist/scripts/afk/afk.js
15
- function formatDuration(ms) {
16
- const secs = Math.floor(ms / 1e3);
17
- if (secs < 60)
18
- return `${secs}s`;
19
- const mins = Math.floor(secs / 60);
20
- const remSecs = secs % 60;
21
- return remSecs > 0 ? `${mins}m ${remSecs}s` : `${mins}m`;
22
- }
23
- var STOP_PATTERNS = {
24
- noTickets: /No tickets found|No issues found|All done/,
25
- skipped: /Ticket skipped/,
26
- preflightFail: /^✗ /m
27
- };
28
- function checkStopCondition(output) {
29
- if (STOP_PATTERNS.noTickets.test(output)) {
30
- return { stop: true, reason: "No more tickets \u2014 all done" };
31
- }
32
- if (STOP_PATTERNS.skipped.test(output)) {
33
- return {
34
- stop: true,
35
- reason: "Ticket was skipped \u2014 update the ticket and re-run"
36
- };
37
- }
38
- if (STOP_PATTERNS.preflightFail.test(output)) {
39
- return { stop: true, reason: "Preflight check failed" };
40
- }
41
- return { stop: false };
42
- }
43
- async function runAfkLoop(scriptDir, maxIterations = 5) {
44
- const onceScript = join(scriptDir, "clancy-once.js");
45
- if (!existsSync(onceScript)) {
46
- console.error(red("\u2717 clancy-once.js not found in"), scriptDir);
47
- return;
48
- }
49
- console.log(dim("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
50
- console.log(dim("\u2502") + bold(" \u{1F916} Clancy \u2014 AFK mode ") + dim("\u2502"));
51
- console.log(dim("\u2502") + dim(` "I'm on it. Proceed to the abandoned warehouse." `) + dim("\u2502"));
52
- console.log(dim("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
53
- const loopStart = Date.now();
54
- for (let i = 1; i <= maxIterations; i++) {
55
- const iterStart = Date.now();
56
- console.log("");
57
- console.log(bold(`\u{1F501} Iteration ${i}/${maxIterations}`));
58
- const result = spawnSync("node", [onceScript], {
59
- encoding: "utf8",
60
- stdio: ["inherit", "pipe", "inherit"],
61
- cwd: process.cwd()
62
- });
63
- const output = result.stdout ?? "";
64
- if (output) {
65
- process.stdout.write(output);
66
- }
67
- const iterElapsed = formatDuration(Date.now() - iterStart);
68
- if (result.error) {
69
- console.error(red(`\u2717 Failed to run clancy-once: ${result.error.message}`));
70
- return;
71
- }
72
- const condition = checkStopCondition(output);
73
- if (condition.stop) {
74
- const totalElapsed2 = formatDuration(Date.now() - loopStart);
75
- console.log("");
76
- console.log(dim(` Iteration ${i} took ${iterElapsed}`));
77
- console.log(`
78
- ${condition.reason}`);
79
- console.log(dim(` Total: ${i} iteration${i > 1 ? "s" : ""} in ${totalElapsed2}`));
80
- return;
81
- }
82
- console.log(dim(` Iteration ${i} took ${iterElapsed}`));
83
- if (i < maxIterations) {
84
- await sleep(2e3);
85
- }
86
- }
87
- const totalElapsed = formatDuration(Date.now() - loopStart);
88
- console.log("");
89
- console.log(green(`\u{1F3C1} Completed ${maxIterations} iterations`) + dim(` (${totalElapsed})`));
90
- console.log(dim(` "That's some good police work."`));
91
- console.log(dim(" Run clancy-afk again to continue."));
92
- }
93
- if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
94
- const scriptDir = dirname(fileURLToPath(import.meta.url));
95
- const maxIterations = parseInt(process.env.MAX_ITERATIONS ?? "5", 10) || 5;
96
- runAfkLoop(scriptDir, maxIterations);
97
- }
98
- export {
99
- checkStopCondition,
100
- runAfkLoop
101
- };
1
+ import{spawnSync as k}from"node:child_process";import{existsSync as h}from"node:fs";import{dirname as w,join as T,resolve as y}from"node:path";import{setTimeout as S}from"node:timers/promises";import{fileURLToPath as g}from"node:url";var e=o=>`\x1B[2m${o}\x1B[0m`,l=o=>`\x1B[1m${o}\x1B[0m`;var u=o=>`\x1B[32m${o}\x1B[0m`,a=o=>`\x1B[31m${o}\x1B[0m`;function p(o){let t=Math.floor(o/1e3);if(t<60)return`${t}s`;let r=Math.floor(t/60),s=t%60;return s>0?`${r}m ${s}s`:`${r}m`}var m={noTickets:/No tickets found|No issues found|All done/,skipped:/Ticket skipped/,preflightFail:/^✗ /m};function A(o){return m.noTickets.test(o)?{stop:!0,reason:"No more tickets \u2014 all done"}:m.skipped.test(o)?{stop:!0,reason:"Ticket was skipped \u2014 update the ticket and re-run"}:m.preflightFail.test(o)?{stop:!0,reason:"Preflight check failed"}:{stop:!1}}async function D(o,t=5){let r=T(o,"clancy-once.js");if(!h(r)){console.error(a("\u2717 clancy-once.js not found in"),o);return}console.log(e("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510")),console.log(e("\u2502")+l(" \u{1F916} Clancy \u2014 AFK mode ")+e("\u2502")),console.log(e("\u2502")+e(` "I'm on it. Proceed to the abandoned warehouse." `)+e("\u2502")),console.log(e("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));let s=Date.now();for(let n=1;n<=t;n++){let x=Date.now();console.log(""),console.log(l(`\u{1F501} Iteration ${n}/${t}`));let c=k("node",[r],{encoding:"utf8",stdio:["inherit","pipe","inherit"],cwd:process.cwd()}),i=c.stdout??"";i&&process.stdout.write(i);let d=p(Date.now()-x);if(c.error){console.error(a(`\u2717 Failed to run clancy-once: ${c.error.message}`));return}let f=A(i);if(f.stop){let b=p(Date.now()-s);console.log(""),console.log(e(` Iteration ${n} took ${d}`)),console.log(`
2
+ ${f.reason}`),console.log(e(` Total: ${n} iteration${n>1?"s":""} in ${b}`));return}console.log(e(` Iteration ${n} took ${d}`)),n<t&&await S(2e3)}let $=p(Date.now()-s);console.log(""),console.log(u(`\u{1F3C1} Completed ${t} iterations`)+e(` (${$})`)),console.log(e(` "That's some good police work."`)),console.log(e(" Run clancy-afk again to continue."))}if(process.argv[1]&&g(import.meta.url)===y(process.argv[1])){let o=w(g(import.meta.url)),t=parseInt(process.env.MAX_ITERATIONS??"5",10)||5;D(o,t)}export{A as checkStopCondition,D as runAfkLoop};