Skip to content

feat(cli): cloud render --json lists the files an upload leaves out - #7631

Merged
jrusso1020 merged 2 commits into
mainfrom
feat/cli-left-out-preflight
Nov 13, 2026
Merged

jrusso1020 merged 2 commits into
mainfrom
feat/cli-left-out-preflight

Conversation

@jrusso1020

@jrusso1020 jrusso1020 commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

hyperframes cloud render --dry-run --json now lists every outside file the upload would leave out, so a wrapper (HyperFrames Desktop first) can tell the person before anything uploads. A full --json run reports the same list, and publish, cloud render and feedback count what they left out in telemetry.

Builds on #7598 (merged); rebased onto main. Refs #7598

Claude Opus 5.5

Why

When an upload leaves out a file the composition points at (a private location, or an outside file reached from a file that came in with an imported project, #7598), the CLI prints a warning naming it. A wrapper that runs the CLI and shows only progress and failures, such as Desktop's cloud render, never shows that warning to the person: the render arrives without the file and nothing says so. The product rule is that a skipped reference is always named to the person, never dropped silently. The CLI had no way to tell a program which files it will leave out.

What changed

  • Preflight: cloud render --dry-run --json. This is the CLI's existing "build and inspect the zip without uploading" pattern, and Desktop already runs it to weigh a project for the cloud. Its archive now carries left_out:
    { "file": "index.html", "reference": "../notes.txt", "path": "../notes.txt", "reason": "received", "levels_up": 1 }
    file is the project file holding the reference (or the link itself, for a symlink), reference is as written, path is from the project folder (absolute only on another drive), reason is blocklisted or received, and levels_up is how many folders above the project it leads (null on another drive).
  • During a real run (--json). The final JSON (--no-wait and waited) carries the same left_out list. Each file also prints a {"event":"left_out",…} line on stderr as it is left out, beside the existing human warning. That line uses the same shape as the existing upload_progress lines, so stderr readers that only parse upload_progress are unaffected.
  • Plumbing. onLeftOut in publishProject.ts now takes a second, structured argument (LeftOutReference, new utils/leftOutReference.ts). Existing one-argument callers still type-check. The warning text is unchanged.
  • Telemetry: cli_upload_left_out, sent once per staging that left something out (new telemetry/uploadLeftOut.ts, through the existing trackEvent). Properties: command (publish / cloud_render / feedback), dry_run, left_out_count, received_count, blocklisted_count, max_levels_up, levels_up_1, levels_up_2, levels_up_3_plus and other_drive. Only counts and depths, never a file name, reference or path; a test checks this.
  • docs/packages/cli.mdx documents left_out under cloud render.

Scope notes

  • publish and feedback --file-issue have no --json or dry-run mode, so they keep the human warning and gain the telemetry. All three paths stage through the same stagePublishFiles rules, so cloud render <dir> --dry-run --json answers "what would be left out" for publish too. Desktop drives only cloud render: its feedback guard refuses --file-issue, and it never runs publish.
  • publishProject.ts (1060 → 1069 lines) and cloud/render.ts (1140 → 1159) were already over 600 lines before this change. The new logic lives in new small files, and those two files only gained the wiring.

Testing

  • render.leftOut.test.ts runs the real CLI with cloud render --dry-run --json on an imported project that has one received and one blocklisted outside reference. It checks archive.left_out, one stderr left_out event per entry, and that the human warning is still printed.
  • leftOutReference.test.ts covers the structured entry for a ../../ reference into a hidden folder (levels_up: 2), an absolute reference in a received file (path made relative to the project), and a symlink to a private file.
  • uploadLeftOut.test.ts covers the event's counts and depth histogram, checks that no name or path appears in the properties, and checks that nothing is sent when nothing was left out.
  • Locally: vitest run on src/commands/cloud, src/utils/publishProject*, publishProxyBake, publish, feedback, and the new tests: 222 passed. oxlint, oxfmt, typecheck, fallow audit and comment-ratchet --base origin/main all pass.

🤖 Generated with Claude Code

— Rames Jusso

Base automatically changed from fix/publish-refuse-received-outside-refs to main November 13, 2026 00:46
@mintlify

mintlify Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Nov 13, 2026, 12:53 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

jrusso1020 and others added 2 commits November 13, 2026 00:47
`cloud render --dry-run --json` now reports `left_out`: each file outside the
project that the upload leaves out, with the file that points at it, the
reference as written, its path from the project, the reason (blocklisted or
received) and how many folders above the project it is. A wrapper can ask
before uploading. A full `--json` run carries the same list in its result and
prints a `{"event":"left_out"}` line on stderr for each, beside the warning a
person reads.

Publish, cloud render and feedback's repro send `cli_upload_left_out` when an
upload leaves something out: counts and folder depths only, never a name or
a path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 121 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (8)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head c5932b3d

The left_out contract matches what hyperframes-internal#10620 parses: same file/reference on the stderr event and the human warning, so Desktop's dedup key holds, and a null levels_up maps to null. CI is green on this head.

Scope

Read in full: leftOutReference.ts, uploadLeftOut.ts, the publishProject.ts wiring (all three leaveOut sites plus the symlink loop in stagePublishFiles), cloud/render.ts (dry run, --no-wait and waited JSON), and publish.ts/feedback.ts. Checked: no telemetry property carries a name or path; --json keeps stdout clean (warning and event both go to stderr, and NO_COLOR comes from Desktop); levels_up on another drive. cli_upload_left_out also fires for each Desktop weigh dry run, with dry_run: true, so upload counts need dry_run = false.

— Genesis reviewer

@jrusso1020
jrusso1020 added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit 2591abf Nov 13, 2026
148 of 164 checks passed
@jrusso1020
jrusso1020 deleted the feat/cli-left-out-preflight branch November 13, 2026 01:53

This branch was successfully deployed

1 active deployment
staging - docs — c5932b3d Deployed Nov 13, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant