Skip to content

feat: third-party web-action contract — offer agentic browser before manual steps#24

Merged
time-attack merged 5 commits into
mainfrom
time-attack/third-party-actions
Jul 23, 2026
Merged

feat: third-party web-action contract — offer agentic browser before manual steps#24
time-attack merged 5 commits into
mainfrom
time-attack/third-party-actions

Conversation

@time-attack

@time-attack time-attack commented Jul 23, 2026

Copy link
Copy Markdown
Owner

What

When a specialist step requires action on a third-party website — registering an API key, creating a vendor/developer account, configuring a dashboard, webhook, OAuth app, or domain verification — gstack previously emitted a manual step list and moved on. Now every dispatcher reads a shared references/THIRD-PARTY-ACTIONS.md contract before doing that:

  1. Detect an agentic browser that can act across the user's logged-in accounts (Aside, via its existing BROWSER-PROVIDERS.md section). Never install it; binary presence is not consent.
  2. STOP and ask one explicit per-task question: drive it now / manual instructions / defer. Consent is never persisted or inferred from an earlier task.
  3. When driving: only the named site and actions; passwords, payment, and identity verification stay user-performed; prefer autofill flows that never expose the secret.
  4. Captured secrets never hit chat output, logs, or shell history — owner-only file or secret store, and verify with one non-mutating API call before claiming success (dashboard fields are often masked placeholders).
  5. Unavailable or declined → manual steps, step marked blocked on user.

How

Follows the established cross-dispatcher pattern (reference contract mirroring webContextContract(), not a '*' overlay): new thirdPartyActionsContract() in generate-skill-tree.ts, one dispatch-protocol sentence, pinned in run-parity.ts (+4 checks × 6 trees, EXPECTED_PARITY_CHECKS 5027 → 5051). Two bisected commits: source change, then mandatory regen.

Evidence

  • bun run test:gstack2: 26/26 files, 0 failures, exit 0
  • bun test: exit 0

Origin

Field failure 2026-07-23: registering a Duffel test API key for the uberflights project required exactly this behavior, and no skill offered it — the agent had to be manually told. The masked-token trap in item 4 comes from that session (the dashboard token field held a masked placeholder; the real value only existed behind the Copy button, caught by a 401 on the verify call).

🤖 Generated with Claude Code


Summary by cubic

Add a shared contract for third‑party web actions. Dispatchers now check for an agentic browser and offer to drive the task with per‑task consent and strict secret handling; fall back to manual if declined.

  • New Features

    • Generate and load references/THIRD-PARTY-ACTIONS.md via thirdPartyActionsContract() for all six skills, and require reading it before directing third‑party site actions.
    • Detect aside; STOP for per‑task choice (drive/manual/defer); scope to the named site/actions; keep passwords/payment/ID checks user‑performed; never echo secrets; store owner‑only or in a secret store; verify tokens with one non‑mutating API call; mark blocked if unavailable/declined.
  • Refactors

    • Parity: add presence/content and dispatcher‑load checks; update EXPECTED_PARITY_CHECKS to 5074 and docs to 5,074 after merging the code‑intelligence contract; bump version to 1.63.0.0 and update CHANGELOG.

Written for commit 915b57b. Summary will update on new commits.

Review in cubic

Sinabina and others added 2 commits July 23, 2026 11:44
…manual steps

When a specialist step needs action on a third-party website (API key
registration, vendor accounts, dashboards), dispatchers now read
references/THIRD-PARTY-ACTIONS.md: detect an agentic browser (Aside),
STOP for per-task consent, keep credentials user-performed, never echo
captured secrets, and verify tokens with one non-mutating call.
Pinned in run-parity.ts (+4 checks x 6 trees, 5027 -> 5051).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 23, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@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.

4 issues found across 16 files

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="scripts/gstack2/run-parity.ts">

<violation number="1" location="scripts/gstack2/run-parity.ts:176">
P2: Parity can still pass after losing several safety boundaries in `THIRD-PARTY-ACTIONS.md`, including no-install, named-site scope, user-only payment/identity steps, protected storage, and blocked manual fallback. Consider asserting each contract section’s critical invariant, not only the consent and API-verification phrases.</violation>
</file>

<file name="scripts/gstack2/generate-skill-tree.ts">

<violation number="1" location="scripts/gstack2/generate-skill-tree.ts:260">
P1: Agent-driven third-party actions can bypass the new contract because the dispatcher only requires it before directing the user to act. The gate should cover both taking the action and asking the user to take it, so the STOP/consent and secret-handling rules are loaded before either workflow.</violation>

<violation number="2" location="scripts/gstack2/generate-skill-tree.ts:528">
P2: Webhook-signing-secret setup can never satisfy this success gate because that secret is not an API credential and cannot be validated by an authenticated read-only API call. Keep the API probe for API credentials and specify an appropriate non-exposing verification path for other secret types.</violation>

<violation number="3" location="scripts/gstack2/generate-skill-tree.ts:530">
P3: The defer choice does not actually defer the workflow because it still emits the manual step list, making options B and C behaviorally identical. A deferred task should be marked blocked and stop without providing the instructions.</violation>
</file>

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

Fix all with cubic | Re-trigger cubic

Comment thread scripts/gstack2/generate-skill-tree.ts Outdated
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work.
4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work. Read \`references/THIRD-PARTY-ACTIONS.md\` before directing the user to act on a third-party website (API key registration, vendor accounts, dashboards).

@cubic-dev-ai cubic-dev-ai Bot Jul 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Agent-driven third-party actions can bypass the new contract because the dispatcher only requires it before directing the user to act. The gate should cover both taking the action and asking the user to take it, so the STOP/consent and secret-handling rules are loaded before either workflow.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/gstack2/generate-skill-tree.ts, line 260:

<comment>Agent-driven third-party actions can bypass the new contract because the dispatcher only requires it before directing the user to act. The gate should cover both taking the action and asking the user to take it, so the STOP/consent and secret-handling rules are loaded before either workflow.</comment>

<file context>
@@ -257,7 +257,7 @@ Web context: <none, optional, local-browser, or production>
 2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
 3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
-4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work.
+4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work. Read \`references/THIRD-PARTY-ACTIONS.md\` before directing the user to act on a third-party website (API key registration, vendor accounts, dashboards).
 5. If an old asset path is unavailable, use \`references/ASSETS.md\`. If legacy prose invokes another retired skill, resolve it through \`references/COMPATIBILITY.md\` and stay inside these six dispatchers.
 6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
</file context>
Suggested change
4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work. Read \`references/THIRD-PARTY-ACTIONS.md\` before directing the user to act on a third-party website (API key registration, vendor accounts, dashboards).
4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work. Read \`references/THIRD-PARTY-ACTIONS.md\` before taking or directing the user to take any action on a third-party website (API key registration, vendor accounts, dashboards).
Fix with cubic

Comment on lines +176 to +179
thirdParty.includes('STOP and ask one explicit question before any browsing')
&& thirdParty.includes('per-task consent')
&& thirdParty.includes('never appears in chat output, logs, or shell history')
&& thirdParty.includes('verify the captured credential with one non-mutating API call'),

@cubic-dev-ai cubic-dev-ai Bot Jul 23, 2026

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: Parity can still pass after losing several safety boundaries in THIRD-PARTY-ACTIONS.md, including no-install, named-site scope, user-only payment/identity steps, protected storage, and blocked manual fallback. Consider asserting each contract section’s critical invariant, not only the consent and API-verification phrases.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/gstack2/run-parity.ts, line 176:

<comment>Parity can still pass after losing several safety boundaries in `THIRD-PARTY-ACTIONS.md`, including no-install, named-site scope, user-only payment/identity steps, protected storage, and blocked manual fallback. Consider asserting each contract section’s critical invariant, not only the consent and API-verification phrases.</comment>

<file context>
@@ -168,6 +168,18 @@ export function runParity(): ParityResult {
+    if (fs.existsSync(thirdPartyPath)) {
+      const thirdParty = fs.readFileSync(thirdPartyPath, 'utf8');
+      check(
+        thirdParty.includes('STOP and ask one explicit question before any browsing')
+          && thirdParty.includes('per-task consent')
+          && thirdParty.includes('never appears in chat output, logs, or shell history')
</file context>
Suggested change
thirdParty.includes('STOP and ask one explicit question before any browsing')
&& thirdParty.includes('per-task consent')
&& thirdParty.includes('never appears in chat output, logs, or shell history')
&& thirdParty.includes('verify the captured credential with one non-mutating API call'),
thirdParty.includes('Never install it, and never treat binary presence as consent to browse')
&& thirdParty.includes('STOP and ask one explicit question before any browsing')
&& thirdParty.includes('then offer A) drive it now through the agentic browser, B) manual instructions, C) defer')
&& thirdParty.includes('per-task consent')
&& thirdParty.includes('touch only the named site and actions')
&& thirdParty.includes('payment, and identity verification remain user-performed steps')
&& thirdParty.includes('never appears in chat output, logs, or shell history')
&& thirdParty.includes('owner-only permissions')
&& thirdParty.includes('Dashboard fields are often masked placeholders')
&& thirdParty.includes('verify the captured credential with one non-mutating API call')
&& thirdParty.includes('provide the manual steps and mark the step blocked on the user'),
Fix with cubic

'',
'3. When driving, touch only the named site and actions. Password entry, new-account credential choice, payment, and identity verification remain user-performed steps: hand off and wait instead of acting. Prefer credential flows that never expose the secret to the agent, such as password-manager autofill or host-native copy.',
'',
'4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify the captured credential with one non-mutating API call before claiming success.',

@cubic-dev-ai cubic-dev-ai Bot Jul 23, 2026

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: Webhook-signing-secret setup can never satisfy this success gate because that secret is not an API credential and cannot be validated by an authenticated read-only API call. Keep the API probe for API credentials and specify an appropriate non-exposing verification path for other secret types.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/gstack2/generate-skill-tree.ts, line 528:

<comment>Webhook-signing-secret setup can never satisfy this success gate because that secret is not an API credential and cannot be validated by an authenticated read-only API call. Keep the API probe for API credentials and specify an appropriate non-exposing verification path for other secret types.</comment>

<file context>
@@ -513,6 +513,25 @@ function webContextContract(): string {
+    '',
+    '3. When driving, touch only the named site and actions. Password entry, new-account credential choice, payment, and identity verification remain user-performed steps: hand off and wait instead of acting. Prefer credential flows that never expose the secret to the agent, such as password-manager autofill or host-native copy.',
+    '',
+    '4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify the captured credential with one non-mutating API call before claiming success.',
+    '',
+    '5. If no agentic browser is available, or the user declines or defers, provide the manual steps and mark the step blocked on the user. Do not recommend or install new products to close the gap.',
</file context>
Suggested change
'4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify the captured credential with one non-mutating API call before claiming success.',
'4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify an API credential with one non-mutating API call before claiming success. For secrets that do not authenticate API calls, use the service\'s appropriate non-exposing verification flow and report exactly what was verified.',
Fix with cubic

'',
'4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify the captured credential with one non-mutating API call before claiming success.',
'',
'5. If no agentic browser is available, or the user declines or defers, provide the manual steps and mark the step blocked on the user. Do not recommend or install new products to close the gap.',

@cubic-dev-ai cubic-dev-ai Bot Jul 23, 2026

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 defer choice does not actually defer the workflow because it still emits the manual step list, making options B and C behaviorally identical. A deferred task should be marked blocked and stop without providing the instructions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/gstack2/generate-skill-tree.ts, line 530:

<comment>The defer choice does not actually defer the workflow because it still emits the manual step list, making options B and C behaviorally identical. A deferred task should be marked blocked and stop without providing the instructions.</comment>

<file context>
@@ -513,6 +513,25 @@ function webContextContract(): string {
+    '',
+    '4. A captured secret (API key, token, webhook signing secret) never appears in chat output, logs, or shell history. Write it to a user-approved local file with owner-only permissions or the user\'s secret store, and keep generated-file destinations out of version control. Dashboard fields are often masked placeholders; verify the captured credential with one non-mutating API call before claiming success.',
+    '',
+    '5. If no agentic browser is available, or the user declines or defers, provide the manual steps and mark the step blocked on the user. Do not recommend or install new products to close the gap.',
+    '',
+  ].join('\n');
</file context>
Suggested change
'5. If no agentic browser is available, or the user declines or defers, provide the manual steps and mark the step blocked on the user. Do not recommend or install new products to close the gap.',
'5. If no agentic browser is available or the user selects manual instructions, provide the manual steps and mark the step blocked on the user. If the user defers, mark the step blocked and stop without providing the manual list. Do not recommend or install new products to close the gap.',
Fix with cubic

Sinabina and others added 3 commits July 23, 2026 12:19
…ctions contract (parity pin 5032+24=5056)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arty-actions (parity pin 5050+24=5074)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@time-attack
time-attack merged commit 18e0c84 into main Jul 23, 2026
7 of 18 checks passed
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