-
Notifications
You must be signed in to change notification settings - Fork 0
fix(ops): operator export scripts honor --help and refuse out-of-repo output paths #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
517ee8a
b1163a3
8dae7dd
212197f
6ca592d
e299770
86e2dc5
404e62c
b2164ef
36ab621
3506160
caff60f
6845789
aad3b20
fab7985
33aad2b
1955e41
b41a2de
4c9cf7e
1c95919
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,9 @@ import { listOutboundProspectFolders } from "./lib/outbound-prospects.mjs"; | |
| import { execFileSync } from "node:child_process"; | ||
| import { localIsoDate } from "./date-utils.mjs"; | ||
| import { sendChannelGuidance } from "./lib/send-channel-guidance.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run prospect:followups -- [--limit=10] [--output=prospects/followup-cockpit.html]`); | ||
| const limitArg = process.argv.find((arg) => arg.startsWith("--limit=")); | ||
| const limit = limitArg ? Number(limitArg.split("=")[1]) : 10; | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
|
|
@@ -403,9 +405,10 @@ const html = `<!doctype html> | |
| </html> | ||
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a prospect has a due follow-up and AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, html); | ||
| writeFileSync(resolvedOutputPath, html); | ||
|
|
||
| console.log(JSON.stringify({ | ||
| status: "created", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |
| import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; | ||
| import { execFileSync } from "node:child_process"; | ||
| import { localIsoDate } from "./date-utils.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run growth:cockpit -- [--output=runs/growth-cockpit.html]`); | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
| const outputPath = outputArg ? outputArg.split("=")[1] : "runs/growth-cockpit.html"; | ||
| const today = localIsoDate(); | ||
|
|
@@ -241,9 +243,10 @@ const html = `<!doctype html> | |
| </html> | ||
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, `${html.replace(/[ \t]+$/gm, "").trimEnd()}\n`); | ||
| writeFileSync(resolvedOutputPath, `${html.replace(/[ \t]+$/gm, "").trimEnd()}\n`); | ||
|
|
||
| console.log(JSON.stringify({ | ||
| status: "created", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,9 @@ import { localIsoDate } from "./date-utils.mjs"; | |
| import { checkProspectReadiness, prospectWarningWeight } from "./lib/prospect-readiness.mjs"; | ||
| import { listOutboundProspectFolders } from "./lib/outbound-prospects.mjs"; | ||
| import { runRepoJson as runJson } from "./lib/runtime-roots.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run growth:doctor -- [--no-checks] [--plain] [--output=runs/growth-doctor.md]`); | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
| const outputPath = outputArg ? outputArg.split("=")[1] : "runs/growth-doctor.md"; | ||
| const skipChecks = process.argv.includes("--no-checks"); | ||
|
|
@@ -233,9 +235,10 @@ ${focusRows || "- No active focus items."} | |
| Do not build more system surface until the current bottleneck is worked. | ||
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, markdown); | ||
| writeFileSync(resolvedOutputPath, markdown); | ||
|
|
||
| const result = { | ||
| status, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |
| import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; | ||
| import { join } from "node:path"; | ||
| import { listOutboundProspectFolders } from "./lib/outbound-prospects.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run prospect:score-cockpit -- [--limit=10] [--output=prospects/lead-scoring-cockpit.html]`); | ||
| const limitArg = process.argv.find((arg) => arg.startsWith("--limit=")); | ||
| const limit = limitArg ? Number(limitArg.split("=")[1]) : 10; | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
|
|
@@ -295,9 +297,10 @@ const html = `<!doctype html> | |
| </html> | ||
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, html); | ||
| writeFileSync(resolvedOutputPath, html); | ||
|
|
||
| console.log(JSON.stringify({ | ||
| status: "created", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,9 @@ import { join } from "node:path"; | |
| import { localIsoDate } from "./date-utils.mjs"; | ||
| import { listOutboundProspectFolders } from "./lib/outbound-prospects.mjs"; | ||
| import { runRepoJson as runJson } from "./lib/runtime-roots.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run market:learn -- [--limit=10] [--output=runs/market-learning-review.md] [--html=runs/market-learning-review.html]`); | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
| const htmlArg = process.argv.find((arg) => arg.startsWith("--html=")); | ||
| const limitArg = process.argv.find((arg) => arg.startsWith("--limit=")); | ||
|
|
@@ -25,10 +27,11 @@ function json(path) { | |
| return existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {}; | ||
| } | ||
|
|
||
| function write(path, content) { | ||
| const dir = path.split("/").slice(0, -1).join("/"); | ||
| function write(path, content, flag = "--output") { | ||
| const resolved = resolveOutputPath(path, { flag }); | ||
| const dir = resolved.split("/").slice(0, -1).join("/"); | ||
| if (dir) mkdirSync(dir, { recursive: true }); | ||
| writeFileSync(path, content); | ||
| writeFileSync(resolved, content); | ||
| } | ||
|
|
||
| function lineValue(content, pattern, fallback = "") { | ||
|
|
@@ -296,7 +299,7 @@ const html = `<!doctype html> | |
| `; | ||
|
|
||
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); | ||
|
Comment on lines
301
to
+302
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With an escaping AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
|
|
||
| console.log(JSON.stringify({ | ||
| status: review.status, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,8 +7,10 @@ import { sendChannelGuidance } from "./lib/send-channel-guidance.mjs"; | |
| import { routedContactPlan } from "./lib/contact-route.mjs"; | ||
| import { classifyOutboundProspect } from "./lib/outbound-prospects.mjs"; | ||
| import { runRepoJson as runJson } from "./lib/runtime-roots.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| const args = process.argv.slice(2); | ||
| handleHelp(args, `Usage: npm run market:proof-cockpit -- [prospects/loom-links.txt] [--limit=5] [--output=runs/market-proof-cockpit.md] [--html=runs/market-proof-cockpit.html]`); | ||
| const inputPath = args.find((arg) => !arg.startsWith("--")) || "prospects/loom-links.txt"; | ||
| const outputArg = args.find((arg) => arg.startsWith("--output=")); | ||
| const htmlArg = args.find((arg) => arg.startsWith("--html=")); | ||
|
|
@@ -27,10 +29,11 @@ function json(path) { | |
| return existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {}; | ||
| } | ||
|
|
||
| function write(path, content) { | ||
| const dir = path.split("/").slice(0, -1).join("/"); | ||
| function write(path, content, flag = "--output") { | ||
| const resolved = resolveOutputPath(path, { flag }); | ||
| const dir = resolved.split("/").slice(0, -1).join("/"); | ||
| if (dir) mkdirSync(dir, { recursive: true }); | ||
| writeFileSync(path, content); | ||
| writeFileSync(resolved, content); | ||
| } | ||
|
|
||
| function clean(value, fallback = "") { | ||
|
|
@@ -415,7 +418,7 @@ const html = `<!doctype html> | |
| `; | ||
|
|
||
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); | ||
|
Comment on lines
420
to
+421
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
|
|
||
| const result = { | ||
| status: cockpitStatus, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,9 @@ import { sendChannelGuidance } from "./lib/send-channel-guidance.mjs"; | |
| import { isValidLoomUrl } from "./lib/loom-url.mjs"; | ||
| import { routedContactPlan, routeToChannel } from "./lib/contact-route.mjs"; | ||
| import { listOutboundProspectFolders } from "./lib/outbound-prospects.mjs"; | ||
| import { handleHelp, resolveOutputPath } from "./lib/operator-cli.mjs"; | ||
|
|
||
| handleHelp(process.argv.slice(2), `Usage: npm run prospect:outbox -- [--limit=20] [--output=prospects/outbox.html]`); | ||
| const limitArg = process.argv.find((arg) => arg.startsWith("--limit=")); | ||
| const limit = limitArg ? Number(limitArg.split("=")[1]) : 20; | ||
| const outputArg = process.argv.find((arg) => arg.startsWith("--output=")); | ||
|
|
@@ -642,9 +644,10 @@ const html = `<!doctype html> | |
| </html> | ||
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an approved send-package prospect exists and AGENTS.md reference: AGENTS.md:L2-L3 Useful? React with 👍 / 👎. |
||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, html); | ||
| writeFileSync(resolvedOutputPath, html); | ||
|
|
||
| console.log(JSON.stringify({ | ||
| status: "created", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
growth:missionreceives an escaping--outputor--html, validation does not reach this call until the final writes. Before then, the section at lines 201-222 runs ten child exporters and may refreshprospects/loom-links.txt; with an escaping--html, it also writes the requested Markdown output first. The command therefore reports a refusal only after overwriting repository artifacts, contrary to the plan's zero-write verification requirement. Resolve both destinations immediately after parsing them, before invoking exporters or updating the Loom template.AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.