@harborppm/cli 0.47.0 → 0.48.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.
- package/README.md +4 -0
- package/dist/app.mjs +785 -474
- package/lib/cli.mjs +51 -1
- package/lib/format.mjs +22 -0
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
notesText,
|
|
36
36
|
voyageText,
|
|
37
37
|
handoverText,
|
|
38
|
+
fogText,
|
|
38
39
|
agentWorkText,
|
|
39
40
|
raidDetail,
|
|
40
41
|
raidList,
|
|
@@ -178,6 +179,10 @@ export const HELP = `harbor: Harbor from the terminal
|
|
|
178
179
|
[--keep ID,ID] [--confirm]
|
|
179
180
|
hand someone's work to the crew
|
|
180
181
|
harbor handback PERSON give it back after time away
|
|
182
|
+
harbor fog [--project P] [--list] tasks nobody has touched for three
|
|
183
|
+
weeks, one at a time: still
|
|
184
|
+
needed, a new date, or drop it
|
|
185
|
+
harbor fog keep TASK it's still needed: out of the fog
|
|
181
186
|
harbor agent [--agent NAME] the tasks given to an AI agent on
|
|
182
187
|
the crew, in the order to do them
|
|
183
188
|
harbor agent report TASK "WHAT YOU DID" [--start] [--agent NAME]
|
|
@@ -190,7 +195,8 @@ export const HELP = `harbor: Harbor from the terminal
|
|
|
190
195
|
"to do", "in play"; --json says doing for In play).
|
|
191
196
|
DATE: YYYY-MM-DD, today, tomorrow, or +N for N days from today.
|
|
192
197
|
Changes show in Harbor's History as yours, "via Harbor CLI". These commands
|
|
193
|
-
never delete; the full-screen app can, as the website can, and asks first
|
|
198
|
+
never delete; the full-screen app can, as the website can, and asks first,
|
|
199
|
+
and so can harbor fog's x (drop it), one task at a time.
|
|
194
200
|
`;
|
|
195
201
|
|
|
196
202
|
export const VERSION = JSON.parse(
|
|
@@ -628,6 +634,20 @@ const DETAIL = {
|
|
|
628
634
|
"",
|
|
629
635
|
' PERSON is a name, an id, or "me".',
|
|
630
636
|
],
|
|
637
|
+
fog: [
|
|
638
|
+
" harbor fog [--project P] in a terminal: the tasks in fog, one",
|
|
639
|
+
" at a time. k still needed (clears the",
|
|
640
|
+
" fog), d a new date, x drop it, s skip,",
|
|
641
|
+
" q stop; then it saves what you chose",
|
|
642
|
+
" harbor fog --list reads them: open tasks nobody has",
|
|
643
|
+
" opened, moved, edited or commented on",
|
|
644
|
+
" for three weeks, longest first",
|
|
645
|
+
" harbor fog keep TASK writes: it's still needed, so it",
|
|
646
|
+
" leaves the fog",
|
|
647
|
+
"",
|
|
648
|
+
" Piped, or with --json, it lists. The one-at-a-time sweep needs full access",
|
|
649
|
+
" (harbor login without --read-only), since dropping a task deletes it.",
|
|
650
|
+
],
|
|
631
651
|
handback: [
|
|
632
652
|
" harbor handback PERSON writes, straight away: gives back",
|
|
633
653
|
" what was handed over for their time",
|
|
@@ -2045,6 +2065,36 @@ export async function run(argv, io = {}) {
|
|
|
2045
2065
|
}
|
|
2046
2066
|
return call("get_voyage_log", { harbor, project }, voyageText, voyageForTerminal);
|
|
2047
2067
|
}
|
|
2068
|
+
case "fog": {
|
|
2069
|
+
const { positionals, values, harbor } = parse(spec(["list"], ["project"]));
|
|
2070
|
+
if (positionals[0] === "keep") {
|
|
2071
|
+
const task = one(positionals.slice(1), "task");
|
|
2072
|
+
return call(
|
|
2073
|
+
"keep_task",
|
|
2074
|
+
{ harbor, task },
|
|
2075
|
+
(r) => `Kept ${r.kept.key ?? r.kept.task} out of the fog: it counts as touched today.`,
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
2078
|
+
none(positionals);
|
|
2079
|
+
const terminal = io.terminal ?? Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
2080
|
+
if (terminal && !values.list && !asJson && hasFullAccess(creds)) {
|
|
2081
|
+
const { fogHere } = await loadApp();
|
|
2082
|
+
await fogHere({
|
|
2083
|
+
source: tokenSource({ creds, save: (c) => writeCredentials(c, env), fetcher }),
|
|
2084
|
+
fetcher,
|
|
2085
|
+
harbor,
|
|
2086
|
+
saved: creds.harbor ?? null,
|
|
2087
|
+
project: values.project,
|
|
2088
|
+
});
|
|
2089
|
+
await stalePromptCache(env);
|
|
2090
|
+
return 0;
|
|
2091
|
+
}
|
|
2092
|
+
return call(
|
|
2093
|
+
"fog",
|
|
2094
|
+
{ harbor, project: values.project, limit: 100 },
|
|
2095
|
+
(r) => fogText(r),
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2048
2098
|
case "handover": {
|
|
2049
2099
|
const { positionals, values, harbor } = parse(
|
|
2050
2100
|
spec(["confirm"], ["to", "until", "note", "keep"]),
|
package/lib/format.mjs
CHANGED
|
@@ -705,3 +705,25 @@ export function exportData(r) {
|
|
|
705
705
|
rows: body.map((cells) => Object.fromEntries(columns.map((c, i) => [c, cells[i] ?? ""]))),
|
|
706
706
|
};
|
|
707
707
|
}
|
|
708
|
+
|
|
709
|
+
/** fog: the open tasks nobody has touched for three weeks, longest first. */
|
|
710
|
+
export function fogText(r, { sweepHint = true } = {}) {
|
|
711
|
+
const where = r.project ? ` in ${r.project}` : "";
|
|
712
|
+
if (!r.inFog) return `No fog${where}: every open task was touched in the last three weeks.`;
|
|
713
|
+
const lines = [
|
|
714
|
+
`${r.inFog} ${r.inFog === 1 ? "task" : "tasks"} in fog${where}: nobody has opened, moved or commented on ${r.inFog === 1 ? "it" : "them"} for three weeks.`,
|
|
715
|
+
"",
|
|
716
|
+
];
|
|
717
|
+
for (const t of r.tasks) {
|
|
718
|
+
const bits = [t.untouched, r.project ? null : t.project, t.due ? `due ${t.due}` : null];
|
|
719
|
+
lines.push(` ${(t.key ?? "").padEnd(7)} ${t.title}`);
|
|
720
|
+
lines.push(` ${bits.filter(Boolean).join(" · ")}`);
|
|
721
|
+
}
|
|
722
|
+
if (r.more) lines.push("", `And ${r.inFog - r.tasks.length} more.`);
|
|
723
|
+
if (sweepHint)
|
|
724
|
+
lines.push(
|
|
725
|
+
"",
|
|
726
|
+
"In a terminal, harbor fog walks through them one at a time: k still needed, d new date, x drop it. harbor fog keep TASK keeps one.",
|
|
727
|
+
);
|
|
728
|
+
return lines.join("\n");
|
|
729
|
+
}
|