fix(ops): operator export scripts honor --help and refuse out-of-repo output paths - #98
fix(ops): operator export scripts honor --help and refuse out-of-repo output paths#98nish3451 wants to merge 20 commits into
Conversation
…-repo output paths Export scripts ignored --help / -h and silently regenerated tracked cockpits, missions, and other operator artifacts on every help invocation. They also accepted --output / --html / --ops / --loom-links paths that could write or overwrite files anywhere on the machine. - New scripts/lib/operator-cli.mjs: handleHelp() prints usage and exits 0 before any work; resolveOutputPath() resolves operator-supplied output paths against the service repository root and refuses escapes via absolute paths, '..' traversal, or symlinks. - All 21 active npm-backed export scripts call handleHelp first and route every write through resolveOutputPath. The internal dashboard's parity scratch file moves from /tmp to a gitignored runs/ path cleaned up afterwards. - test-active-operator-surfaces.mjs: every active export script must exit 0 on --help, print usage, and leave live metrics, the proof library, and the daily money mission untouched; traversal / absolute / html / loom-links / ops / symlink escape probes are refused without creating files.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Warning Review limit reached
Next review available in: 34 minutes Limit details: You’ve used the included review currently available. Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (11)
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 517ee8a6e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| while (!existsSync(existing)) { | ||
| const parent = dirname(existing); | ||
| if (parent === existing) break; | ||
| existing = parent; | ||
| } |
There was a problem hiding this comment.
Reject dangling output symlinks
When the requested output itself is a dangling symlink to a nonexistent external file, existsSync(existing) returns false, so this loop climbs past the symlink and validates only its in-repository parent. The subsequent writeFileSync follows the dangling link and creates the external target, leaving every exporter using this helper vulnerable to the out-of-repository write the change is intended to prevent; inspect path components with lstat/readlink or otherwise reject symlinks before writing.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| if (outputDir) mkdirSync(outputDir, { recursive: true }); | ||
| writeFileSync(outputPath, `${lines.join("\n")}\n`); | ||
| writeFileSync(resolveOutputPath(outputPath), `${lines.join("\n")}\n`); |
There was a problem hiding this comment.
Validate the queue path before creating its directory
For an escaping value such as --output=/tmp/new-parent/queue.md, the preceding mkdirSync(outputDir) creates /tmp/new-parent before this call detects the escape and exits. The command therefore still modifies the filesystem outside the repository despite reporting that the path was refused; resolve and validate the path first, then derive and create its directory from the validated result.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Validate the cockpit path before regenerating dependencies
When --output escapes the repository, this validation is reached only after the calls near the top of the script have run the recording, scoring, outbox, mission, metrics, proof, doctor, and sender exporters. Consequently, an invocation such as growth:cockpit -- --output=/tmp/x exits with a refusal but has already overwritten numerous default repository artifacts—the same accidental regeneration this safety work is meant to avoid. Resolve the requested output immediately after parsing arguments, before invoking any child exporter.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1163a38c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ["scripts/export-market-benchmark.mjs", ["--ops=/tmp/escape-ops.md"], "/tmp/escape-ops.md"] | ||
| ] | ||
| for (const [script, args, escapePath] of escapeProbes) { | ||
| rmSync(escapePath, {force: true}) |
There was a problem hiding this comment.
Isolate escape fixtures before deleting them
When /tmp/escape-cockpit.html, /tmp/escape-ops.md, /tmp/escape-metrics.md, or even /escape-mission.html already belongs to another process or user, this loop unconditionally deletes that file before running the probe; the later escape-symlink-outside cleanup similarly removes a fixed sibling directory recursively. Because npm test runs this script and CI commonly runs with broad filesystem permissions, a test invocation can destroy unrelated data. Create a separate external directory with mkdtempSync and clean up only that uniquely owned directory.
Useful? React with 👍 / 👎.
| const parityScratchPath = "runs/.internal-dashboard-parity.md"; | ||
| const parity = runJson(["scripts/check-market-parity-readiness.mjs", "--skip-kit", `--output=${parityScratchPath}`]); | ||
| try { rmSync(join(serviceRoot, parityScratchPath), { force: true }); } catch {} |
There was a problem hiding this comment.
Preserve pre-existing dashboard scratch files
When runs/.internal-dashboard-parity.md already exists, every dashboard export passes that fixed path to the parity exporter, which overwrites it, and then deletes it unconditionally. This silently destroys repository data that predates the command; use a uniquely created temporary path and clean it in a finally block, or refuse to replace an existing file.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8dae7ddbd3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| write(outputPath, markdown); | ||
| write(opsPath, markdown); | ||
| write(htmlPath, html); | ||
| write(opsPath, markdown, "--ops"); |
There was a problem hiding this comment.
Validate every benchmark path before writing
When a secondary destination escapes the repository, such as --ops=/tmp/escape-ops.md or an escaping --html, the first write(outputPath, markdown) has already overwritten the default benchmark before the later write rejects that destination; the earlier metrics exporter also regenerates live-metrics.md. Resolve and validate all three requested paths before running exporters or writing any artifact so a refused invocation remains side-effect free.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 212197fdbe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| function write(path, content) { | ||
| const dir = path.split("/").slice(0, -1).join("/"); | ||
| const resolved = resolveOutputPath(path); |
There was a problem hiding this comment.
Validate mission outputs before running exporters
When growth:mission receives an escaping --output or --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 refresh prospects/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 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ca592d6ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| write(resolveOutputPath(outputPath), markdown); | ||
| write(resolveOutputPath(htmlPath, { flag: "--html" }), html); |
There was a problem hiding this comment.
Validate dashboard destinations before regenerating dependencies
When either destination escapes the repository, validation is deferred until these final writes, after the calls at lines 51–73 have already regenerated growth metrics, the doctor report, proof surfaces, rehearsal artifacts, and the sender guide; an escaping --html also overwrites the Markdown dashboard before being rejected on line 490. Resolve both destinations immediately after parsing so a refused dashboard invocation remains side-effect free.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); |
There was a problem hiding this comment.
Validate proof-cockpit HTML before writing artifacts
When --html escapes the repository, the command reaches this validation only after check-market-proof-run.mjs has overwritten runs/market-proof-run-check.md and line 420 has overwritten the requested Markdown cockpit. The command then reports refusal despite already modifying repository artifacts, so resolve both destinations before invoking the checker or performing either write.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); |
There was a problem hiding this comment.
Validate learning-review HTML before regenerating metrics
With an escaping --html, this second write rejects the path only after the metrics exporter at line 62 has refreshed growth-brain/ops/live-metrics.md and line 301 has overwritten the Markdown learning review. Resolve both output paths before running exporters or writing either artifact so an invalid destination cannot cause partial regeneration.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); |
There was a problem hiding this comment.
Validate rehearsal HTML before writing Markdown
When only --html escapes the repository, line 394 has already overwritten the Markdown rehearsal report before this call rejects the HTML destination. Pre-resolve both requested paths before the first write so a refused invocation does not leave a partially updated artifact set.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| write(outputPath, markdown); | ||
| write(htmlPath, html); | ||
| write(htmlPath, html, "--html"); |
There was a problem hiding this comment.
Validate sender-guide HTML before writing Markdown
When --html points outside the repository, the Markdown sender guide is overwritten on line 255 before this call validates and rejects the HTML path. Resolve both destinations before either write so a refused command cannot partially refresh the guide.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e299770d68
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Validate the doctor output before regenerating reports
When --output escapes the repository, validation occurs only here, after the metrics and rehearsal exporters have already overwritten their default artifacts at lines 151–154. Resolve the requested destination before invoking those exporters so a refused growth:doctor command remains side-effect free.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Validate recording cockpit output before drafting messages
When an active prospect exists and --output escapes the repository, the mapping at lines 79–81 runs draft-prospect-message.mjs, which overwrites that prospect's next-message.md, before this validation rejects the destination. Resolve the output before processing prospects so an invalid cockpit invocation cannot mutate prospect records.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Validate follow-up output before refreshing messages
When a prospect has a due follow-up and --output escapes the repository, ensureMessage() at line 94 overwrites the prospect's next-message.md before this late validation exits. Validate the destination before enumerating due prospects so a refused follow-up export does not alter repository data.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Validate outbox output before regenerating messages
When an approved send-package prospect exists and --output escapes the repository, the outbox calls ensureMessage() at line 121 and overwrites next-message.md before reaching this validation. Resolve the destination before building the prospect list so an invalid outbox request cannot modify prospect artifacts.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b2164ef995
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| existing = parent; | ||
| } | ||
| const realRoot = realpathSync(root); | ||
| const realRel = relative(realRoot, realpathSync(existing)); |
There was a problem hiding this comment.
Replace hard-linked destinations atomically
When the requested in-repository destination already exists as a hard link to a file outside the repository on the same filesystem, realpathSync(existing) still reports the safe-looking in-repository pathname, so this check passes and the exporters' subsequent writeFileSync calls truncate the shared external inode. Reject multiply linked destination files or write to a new temporary file and atomically rename it over the destination so the out-of-repository write guarantee also survives hard-link tampering.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 36ab621630
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); | ||
| const outputDir = resolvedOutputPath.split("/").slice(0, -1).join("/"); |
There was a problem hiding this comment.
Derive resolved output directories with path.dirname
On Windows, resolveOutputPath() returns a platform-native absolute path such as C:\repo\new\metrics.md, so splitting it on "/" produces no parent directory. When a user selects an in-repository output whose parent does not yet exist, mkdirSync is skipped and writeFileSync fails with ENOENT; this pattern is repeated in several modified exporters. Use path.dirname(resolvedOutputPath) so the documented recursive directory creation works across platforms.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fab7985d30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
| const parity = runJson(["scripts/check-market-parity-readiness.mjs", "--skip-kit", "--output=/tmp/tinystudio-internal-dashboard-parity.md"]); | ||
| const parityScratchPath = "runs/.internal-dashboard-parity.md"; | ||
| const parity = runJson(["scripts/check-market-parity-readiness.mjs", "--skip-kit", `--output=${parityScratchPath}`]); |
There was a problem hiding this comment.
Validate the parity scratch path before invoking the checker
When the ignored runs/ path is a symlink to a directory outside the repository, this child command writes .internal-dashboard-parity.md through that symlink and the following cleanup deletes the external file. The invoked checker merely joins serviceRoot with --output and passes it to writeFileSync (scripts/check-market-parity-readiness.mjs:13,28-31), bypassing resolveOutputPath; validate this scratch destination or use a safely created temporary directory before running the checker.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33aad2b328
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ? "prospects/kit-proof-run-loom-links.txt" | ||
| : "prospects/loom-links.txt"; | ||
|
|
||
| const resolvedLoomLinksPath = resolveOutputPath(loomLinksPath, { flag: "--loom-links" }); |
There was a problem hiding this comment.
Validate the proof-run parity scratch path
When the ignored prospects/ directory is a symlink outside the repository and the caller supplies a safe --loom-links path under runs/, this validation succeeds, but the section at lines 207–214 still invokes check-market-parity-readiness.mjs with prospects/market-proof-run-parity.md. That checker directly joins the path to serviceRoot and writes it (scripts/check-market-parity-readiness.mjs:12-13,28-31,227), after which this exporter deletes it, so the command can write and remove an external file despite validating both operator-provided destinations; validate the parity scratch destination as well or create it in a safely owned temporary directory.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1955e418a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Anchor prospect reads to the service root
When SERVICE_REPO_ROOT differs from the current working directory, this now writes the cockpit under the service repository, but the prospect scan at line 45 still reads the relative prospects directory from the current working directory. Consequently, running the exporter from another workspace can copy that workspace's prospect names and details into the service repository's HTML; resolve the input root against serviceRoot as well before generating the output.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b41a2de5d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| `; | ||
|
|
||
| const outputDir = outputPath.split("/").slice(0, -1).join("/"); | ||
| const resolvedOutputPath = resolveOutputPath(outputPath); |
There was a problem hiding this comment.
Anchor teleprompter inputs to the service root
When SERVICE_REPO_ROOT differs from the current working directory, this writes the teleprompter into the service repository, but the prospect scan at line 73 still reads the relative prospects directory from the current working directory. The generated service-repository cockpit can therefore expose another checkout's prospect details and omit the intended repository's records; resolve the input root against serviceRoot before generating the output.
AGENTS.md reference: AGENTS.md:L2-L3
Useful? React with 👍 / 👎.
…-cli-help # Conflicts: # scripts/export-growth-metrics.mjs # scripts/export-internal-dashboard.mjs # scripts/export-market-benchmark.mjs # scripts/export-market-proof-run.mjs # scripts/export-proof-library.mjs # scripts/export-recording-cockpit.mjs # scripts/export-recording-queue.mjs # scripts/export-recording-rehearsal-check.mjs # scripts/export-recording-teleprompter.mjs # scripts/export-sender-setup-guide.mjs # scripts/test-active-operator-surfaces.mjs
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Correction to my closing comment above: the keeper for this cluster is #160, not #56. I had wrongly concluded that This PR stays closed either way — its content is superseded by what is already on |
Closes the lane item:
[unreviewed-by-grok] Operator export scripts ignore --help and write/overwrite cockpits and mission artifacts anywhere.What
Operator export scripts ignored
--help/-hand silently regenerated tracked ops artifacts (cockpits likegrowth-cockpit,sales-cockpit,recording-cockpit; missions likedaily-money-mission; pluslive-metrics,proof-library,sender-setup-guide,11-10-proof-run,competitive-proof-matrix,market-parity-benchmark-2026) on every help invocation. They also accepted--output/--html/--ops/--loom-linkspaths that escape the repository and could write or overwrite files anywhere on the machine.Changes
scripts/lib/operator-cli.mjshandleHelp(args, usage)— prints usage and exits 0 before any work when--help/-his present.resolveOutputPath(value, {flag, fallback})— resolves operator-supplied output paths against the service repository root and refuses paths that escape it via absolute paths,..traversal, or symlink escapes (clear error, exit 1, no file created).handleHelpfirst and route every write (and the proof-run loom-links path) throughresolveOutputPath.export-internal-dashboard.mjsno longer writes its parity scratch file to/tmp; it uses a gitignoredruns/scratch path cleaned up after use.test-active-operator-surfaces.mjsextended:--help, print usage, and leavelive-metrics.md, the proof library, and the daily money mission untouched;--output=../…, absolute/tmp/…,../../html path,--loom-links=../…,--ops=/tmp/…, and an in-repo symlink escape are all refused without creating the file.Retired export scripts (no npm wiring, e.g.
export-owned-*,export-full-stack-growth-map) are not part of the active operator surface and are intentionally untouched.Validation
npm run ci: every suite passes (service-engine, sales-intake, active-offer-projection, active-operator-surfaces, direction-proof-gate, client-readiness-contract, validated-service-client, client-acceptance-gates, product-truth, human-service-kit, design-system-proving-lab, retention, agency-defaults, claims, send-readiness, all public-page suites, andnode --checkon every script). 630 checks, 0 failures.node scripts/export-growth-metrics.mjs --helpandnode scripts/export-proof-library.mjs --helpprint usage, exit 0, and leave tracked artifacts untouched;--output=/tmp/…and--output=../…are refused with exit 1 and create nothing.Relationship to existing PRs
Prior attempts at this same lane item: #36, #44, #55 (all stale bases) and #95 (recording exporters only, fresh but narrower). This is a fresh implementation on current main covering the full active export surface.