Skip to content

feat(nextactions): send Insta-Hints and render Next: affordance#32

Merged
jwfing merged 2 commits into
develfrom
feature/next-actions
Jul 14, 2026
Merged

feat(nextactions): send Insta-Hints and render Next: affordance#32
jwfing merged 2 commits into
develfrom
feature/next-actions

Conversation

@jwfing

@jwfing jwfing commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

Send Insta-Hints: 1 and render a Next: affordance after workflow-spine commands (project create, service add, branch create, deploy).

  • Insta-Hints: 1 added at the single ApiClient.fetch choke point.
  • Pure nextActionsLines() + renderNextActions() in src/util.ts with a neutral-opinsta command map; an unknown op degrades to reason-only (never crashes); gated hints are marked. Reads nextActions from the response body.

Depends on InsForge/insta-platform#30. Design: docs/superpowers/specs/2026-07-13-platform-next-actions-design.md.

Test plan

  • npm run typecheck — clean
  • npm test50/50; unit tests cover mapped/unknown/gated/empty ops and that metrics/logs render with the compute target.

🤖 Generated with Claude Code


Summary by cubic

Show a "Next:" hint after project create, service add, branch create, and deploy. Also send Insta-Hints: 1 on all API calls to request server-provided next steps.

  • New Features
    • Add Insta-Hints: 1 in ApiClient.fetch to request next actions.
    • Read nextActions from response bodies and render a "Next:" affordance.
    • Add nextActionsLines() and renderNextActions(); unknown ops fall back to reason-only; gated actions are marked.
    • Hook rendering into project create, services add, branch create, and deploy.
    • Default metrics/logs hints to compute so commands run out of the box.

Written for commit c6d4949. Summary will update on new commits.

Review in cubic

@jwfing jwfing left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Summary

Small, well-scoped change that sends Insta-Hints: 1 at the single ApiClient.fetch choke point and renders a Next: affordance from the response body after the four workflow-spine commands; the core logic is a pure, unit-tested nextActionsLines() that degrades gracefully on unknown ops.

Requirements context

No matching spec/plan found in this repo. The PR body references docs/superpowers/specs/2026-07-13-platform-next-actions-design.md, but there is no docs/ directory at the PR head (c6d4949) — the design doc and the server contract appear to live in the dependency InsForge/insta-platform#30. This review therefore assesses against the PR description and the CLI's own command surface (src/index.ts). I verified locally: tsc --noEmit is clean and vitest is 50/50 green.

Findings

Critical

(none)

Suggestion

Functionality — metrics/logs mapping passes args.target through verbatim (src/util.ts:47-48). The CLI's metrics/logs commands only accept target: db|compute (src/index.ts:127,130). The default ?? 'compute' is correct and tested, but if the platform ever emits a neutral op with args.target set to the service vocabulary (services are postgres|storage|compute), the rendered hint would be insta metrics postgres — which is not a runnable command. Worth confirming the platform contract (#30) emits db/compute, or normalizing postgres → db here. Non-blocking since I can't see what #30 actually sends.

Software engineering — mapped-op-with-args cases beyond metrics/logs are untested (test/util.test.ts:25-56). Good coverage on mapped/unknown/gated/empty and the metrics/logs default. The deploy branch-flag path (a.branch → --branch), secrets.set, and approvals.approve mappings aren't asserted, so a future edit to those command strings wouldn't be caught by a test. A couple more one-line cases would lock the rendered commands.

Functionality — Next: prints before trailing side-effects in projectCreate (src/commands/project.ts:30). renderNextActions(out.nextActions) runs before tryInstallObserve() and installSkills(), both of which emit their own output. That pushes the Next: block up into scrollback rather than leaving it as the last thing the user sees. Consider rendering hints after the install steps for the create path so the affordance stays at the bottom. Cosmetic.

Information

  • Security — secrets.set hint interpolates args.value into printed output (src/util.ts:45). The rendered string is only displayed, never executed, so there's no injection risk. Just flagging that if the platform ever populates args.value with a real secret it would be echoed to the terminal/stdout — the placeholder <value> fallback is the right default; keep it that way server-side.
  • Security — no auth/authorization surface touched. The only header change is a static Insta-Hints: 1 (src/api.ts:59); no secrets, tokens, or PII are added to requests or responses. nextAction.reason/args are platform-controlled strings printed via info() — displayed, not evaluated.
  • Functionality — none of the four wired commands (project create, services add, branch create, deploy) has a --json mode, so appending human-readable Next: lines can't corrupt machine-readable output. Reads are correctly sourced from the body: out.nextActions for request() callers and res.body.nextActions for rawRequest() callers. The gated (HTTP 202) path returns early via handleApproval before rendering, which is correct.
  • Performance — no concerns. Pure string building over a small array; no queries, loops of concern, or hot-path work.

Verdict

approved (informational — a human still gives the explicit GitHub approval). Zero Critical findings; the Suggestions above are non-blocking. Clean, tested, conventional diff.

@Fermionic-Lyu Fermionic-Lyu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, Approved. (Relaying John-bot's approved verdict — approved with the maintainer account, since John-bot can't approve its own PR.)

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 7 files

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/util.ts">

<violation number="1" location="src/util.ts:45">
P2: The `deploy` next-action mapping renders `insta deploy [--branch <b>]` but the deploy command requires a `<dir>` or `--image <url>` — running the hint as-is will fail with a usage error. Consider including a placeholder for the required argument, e.g. `insta deploy <dir> --branch <name>`. The mapping also doesn't handle `--group` which the actual command supports and the deploy response includes (`res.body.group`).</violation>

<violation number="2" location="src/util.ts:46">
P3: The `secrets.set` mapping uses `<NAME>` (uppercase) for the name placeholder while `service.add` uses `<name>` (lowercase). Keeps the affordance consistent.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/util.ts
// Neutral op → an `insta` command string. Unknown ops fall back to reason-only (no crash).
const OP_COMMAND: Record<string, (a: Record<string, unknown>) => string> = {
'service.add': (a) => `insta services add ${a.type ?? '<type>'} ${a.name ?? '<name>'}`,
deploy: (a) => `insta deploy${a.branch ? ` --branch ${a.branch}` : ''}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The deploy next-action mapping renders insta deploy [--branch <b>] but the deploy command requires a <dir> or --image <url> — running the hint as-is will fail with a usage error. Consider including a placeholder for the required argument, e.g. insta deploy <dir> --branch <name>. The mapping also doesn't handle --group which the actual command supports and the deploy response includes (res.body.group).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/util.ts, line 45:

<comment>The `deploy` next-action mapping renders `insta deploy [--branch <b>]` but the deploy command requires a `<dir>` or `--image <url>` — running the hint as-is will fail with a usage error. Consider including a placeholder for the required argument, e.g. `insta deploy <dir> --branch <name>`. The mapping also doesn't handle `--group` which the actual command supports and the deploy response includes (`res.body.group`).</comment>

<file context>
@@ -37,6 +37,34 @@ export function handleApproval(res: { status: number; body: any }): boolean {
+// Neutral op → an `insta` command string. Unknown ops fall back to reason-only (no crash).
+const OP_COMMAND: Record<string, (a: Record<string, unknown>) => string> = {
+  'service.add': (a) => `insta services add ${a.type ?? '<type>'} ${a.name ?? '<name>'}`,
+  deploy: (a) => `insta deploy${a.branch ? ` --branch ${a.branch}` : ''}`,
+  'secrets.set': (a) => `insta secrets set ${a.name ?? '<NAME>'} ${a.value ?? '<value>'}`,
+  metrics: (a) => `insta metrics ${a.target ?? 'compute'}`,
</file context>
Suggested change
deploy: (a) => `insta deploy${a.branch ? ` --branch ${a.branch}` : ''}`,
deploy: (a) => `insta deploy ${a.dir ?? '<dir>'}${a.branch ? ` --branch ${a.branch}` : ''}${a.group ? ` --group ${a.group}` : ''}`,

Comment thread src/util.ts
const OP_COMMAND: Record<string, (a: Record<string, unknown>) => string> = {
'service.add': (a) => `insta services add ${a.type ?? '<type>'} ${a.name ?? '<name>'}`,
deploy: (a) => `insta deploy${a.branch ? ` --branch ${a.branch}` : ''}`,
'secrets.set': (a) => `insta secrets set ${a.name ?? '<NAME>'} ${a.value ?? '<value>'}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The secrets.set mapping uses <NAME> (uppercase) for the name placeholder while service.add uses <name> (lowercase). Keeps the affordance consistent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/util.ts, line 46:

<comment>The `secrets.set` mapping uses `<NAME>` (uppercase) for the name placeholder while `service.add` uses `<name>` (lowercase). Keeps the affordance consistent.</comment>

<file context>
@@ -37,6 +37,34 @@ export function handleApproval(res: { status: number; body: any }): boolean {
+const OP_COMMAND: Record<string, (a: Record<string, unknown>) => string> = {
+  'service.add': (a) => `insta services add ${a.type ?? '<type>'} ${a.name ?? '<name>'}`,
+  deploy: (a) => `insta deploy${a.branch ? ` --branch ${a.branch}` : ''}`,
+  'secrets.set': (a) => `insta secrets set ${a.name ?? '<NAME>'} ${a.value ?? '<value>'}`,
+  metrics: (a) => `insta metrics ${a.target ?? 'compute'}`,
+  logs: (a) => `insta logs ${a.target ?? 'compute'}`,
</file context>
Suggested change
'secrets.set': (a) => `insta secrets set ${a.name ?? '<NAME>'} ${a.value ?? '<value>'}`,
'secrets.set': (a) => `insta secrets set ${a.name ?? '<name>'} ${a.value ?? '<value>'}`,

@jwfing jwfing merged commit 80da15e into devel Jul 14, 2026
2 checks passed
@tonychang04 tonychang04 mentioned this pull request Jul 15, 2026
tonychang04 added a commit that referenced this pull request Jul 15, 2026
Ships: optional project-create name (paste-runnable one-liner, #34),
next-action Next: hints (#32), insta compute start/stop/suspend/status
lifecycle commands, agents.instacloud.com canonical docs (#31).


Claude-Session: https://claude.ai/code/session_01GMbAe5K1RfwaAcge5inX7P

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants