Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions skills/iac-code/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Treat a bridge error returned before job creation as the authoritative outcome f
```json
{
"channel": "codex",
"pipelineName": "selling_solution_first",
"permissionWaitPolicy": {
"residentTimeoutSeconds": null,
"subPipelineTimeoutSeconds": null,
Expand All @@ -37,10 +38,10 @@ Treat a bridge error returned before job creation as the authoritative outcome f
}
```

`channel` stores only the channel identifier; the bridge adds the `skill/` prefix before sending it to iac-code. `permissionWaitPolicy` applies only to the temporary A2A server owned by this Skill: `null` timeouts mean unlimited waits, positive finite values set resident/Sub Pipeline limits, and grace is a non-negative finite value. Finite values cannot exceed 10 years; use `null` instead of an arbitrarily large number for an unlimited resident or Sub Pipeline wait. The bridge validates and converts this object into server configuration; it never sends the policy through A2A message metadata. Missing fields use the defaults shown above. The bridge rejects unknown configuration fields. If the file or a field is absent, no corresponding override is applied. Never derive these values from the user's request, ask the user for them, or create, edit, or reveal this install-local configuration during an infrastructure task.
`channel` stores only the channel identifier; the bridge adds the `skill/` prefix before sending it to iac-code. `pipelineName` selects the implementation used only after Pipeline mode is chosen: `selling_solution_first` is the default, while the legacy `selling` flow is used only when this install-local file explicitly selects it. `permissionWaitPolicy` applies only to the temporary A2A server owned by this Skill: `null` timeouts mean unlimited waits, positive finite values set resident/Sub Pipeline limits, and grace is a non-negative finite value. Finite values cannot exceed 10 years; use `null` instead of an arbitrarily large number for an unlimited resident or Sub Pipeline wait. The bridge validates and converts this object into server configuration; it never sends the policy through A2A message metadata. The bridge rejects unknown configuration fields and invalid Pipeline names. If `config.json` or `pipelineName` is absent, Pipeline mode uses `selling_solution_first`; other absent fields keep their existing defaults. Never derive these values from the user's request, ask the user for them, or create, edit, or reveal this install-local configuration during an infrastructure task.

Normal is the default, including concrete resource queries/changes, template work, troubleshooting, and deployment of a clear target. Use `--mode pipeline --pipeline-name selling` only when the user explicitly requests it or the request genuinely needs the fixed candidate-architecture, cost-comparison, plan-confirmation, and deployment flow. Questions, permissions, tool use, or deployment alone do not select Pipeline. When uncertain, use normal.
Start performs a non-secret configuration preflight through the Runtime. An incomplete LLM provider/API Key returns `llm_not_configured` and stops before creating a job. Selling Pipeline also requires complete Alibaba Cloud credentials and otherwise returns `cloud_credentials_not_configured`. Normal mode may continue without cloud credentials for work that does not call cloud APIs; report its preflight warning rather than claiming cloud operations are available.
Normal is the overall default, including concrete resource queries/changes, template work, troubleshooting, and deployment of a clear target. Use `--mode pipeline` only when the user explicitly requests it or the request genuinely needs the candidate-architecture, cost-comparison, plan-confirmation, and deployment flow. Pipeline mode uses solution-first unless the installed configuration explicitly selects legacy selling. Questions, permissions, tool use, or deployment alone do not select Pipeline. When uncertain, use normal.
Start performs a non-secret configuration preflight through the Runtime. An incomplete LLM provider/API Key returns `llm_not_configured` and stops before creating a job. Both supported Pipelines require complete Alibaba Cloud credentials and otherwise return `cloud_credentials_not_configured`. Normal mode may continue without cloud credentials for work that does not call cloud APIs; report its preflight warning rather than claiming cloud operations are available.
3. `--follow` consumes the event stream until the next parent/candidate step boundary, permission, user question, candidate selection, `turn_completed`, or terminal state. It writes every parent `step_started`/`step_completed`/`step_failed` and candidate `candidate_step_started`/`candidate_step_completed`/`candidate_step_failed` boundary plus low-frequency bounded heartbeats to stderr; stdout contains one bounded JSON result. A boundary result sets `boundaryReached: true`, `presentationRequired: true`, and provides ready-to-display localized strings in `userUpdates`. Before invoking another tool, emit every `userUpdates` string in a user-visible assistant text block, including the Step 1/2 conclusion already embedded in completed-step updates. Never leave these updates only in reasoning, Bash output, a tool description, or the final summary. After that visible text block, immediately call `follow` again with the returned cursor. Do not treat `boundaryReached` as completion. Do not expand this into raw tool-event or token-delta output.
While it is running, do not independently answer the infrastructure task or ask a parallel business question. Only ask the user when the current result contains `inputRequired`.
4. If follow reaches its bounded wait window, call the diagnostic follow command again with the returned cursor:
Expand All @@ -50,6 +51,7 @@ Treat a bridge error returned before job creation as the authoritative outcome f
```

The recommended wait is 60 seconds and the bridge enforces a 120-second maximum even if a larger value is supplied.
If a result says `state: input-required` but does not contain `inputRequired`, there is no user boundary to answer. Report its `latestText` or error, keep the same job unchanged, and stop. Never call `continue`, repeat `respond`, call `cancel`, or start a replacement job unless the user explicitly requests that action.

5. When `state` is `turn_completed`, treat `finalText` and `artifacts` as the authoritative normal-turn result. When a Pipeline reaches any terminal state, including `completed`, `failed`, `canceled`, or `rejected`, treat `pipelineResult` and `artifacts` as its authoritative result and present its success or failure details directly. If rollback cleanup is pending, the bridge automatically runs a cleanup-only normal task in the same context before returning the Pipeline result; keep following it and handle any returned permission normally. If cleanup is `failed` or `unavailable`, report that manual inspection or retry is required and do not claim it succeeded. Never send a synthetic cleanup prompt or a follow-up merely to retrieve or summarize an existing result. Never recover an answer from Session files, spool files, logs, or raw tool-result files.
6. To send the next natural-language message in the same normal conversation, or after a completed Pipeline has handed the same conversation to normal mode, write it to another workspace prompt file and continue the existing job:
Expand All @@ -68,24 +70,20 @@ python3 scripts/iac_code.py poll --job-id <job-id> --cursor <cursor> --wait-seco

## User input

When `inputRequired` is present, preserve every correlation field in the response. Never reuse an answer file from another request.
Treat every `inputRequired` as a hard user-interaction boundary. Present it through the outer Agent's native user-question or approval UI and stop until the user explicitly answers that specific boundary. If no native UI is available, ask in a visible assistant turn and stop. Never infer, recommend-and-select, or submit an answer from the original infrastructure request, a prior answer, an outer tool-execution approval, a default, or the fact that only one option is available. Do not write an answer file or invoke `respond` before the user's answer arrives. Preserve every correlation field in the response, and never reuse an answer file from another request.

- For `permission`, apply the outer Agent's own equivalent permission policy. If the same operation would proceed without asking when invoked directly by the outer Agent, respond `allow_once`; if that policy would deny, respond `deny`; otherwise ask the user. iac-code has already applied its own allow/deny rules, and the outer Agent must not override an iac-code denial. Base the decision on `title`, `purpose`, `effect`, `target`, `isReadOnly`, `deploymentSummary`, and `safeSummary`; do not infer safety from the internal `toolName` alone. When asking about deployment, show the provided plan, region, stack, template, total price, and per-resource prices without exposing raw tool input.
- For `ask_user_question`, present the current prompt and options without inventing a second question. Accept a listed option. Accept free text only when `allowFreeText` is `true`; when present, show `freeTextPrompt` with the input.
- For `candidate_selection`, first present every option's `summary`, render `architectureDiagram` as Mermaid when present, and show `totalMonthlyCost` plus `costItems`. Do not invent missing details or replace these prices with a rough estimate. Then return the selected candidate ID/index requested by the envelope.
- For `permission`, always ask the user to choose one of the returned actions, including for read-only or apparently safe operations. The original request and the outer Agent's permission policy do not authorize an iac-code permission boundary. iac-code has already applied its own allow/deny rules, and the outer Agent must not override an iac-code denial. Present `title`, `purpose`, `effect`, `target`, `isReadOnly`, `deploymentSummary`, and `safeSummary`; do not expose raw tool input or infer safety from the internal `toolName` alone.
- For `ask_user_question`, present the current prompt and options without inventing a second question, then wait for the answer. Accept a listed option. Accept free text only when `allowFreeText` is `true`; when present, show `freeTextPrompt` with the input.
- For `candidate_selection`, present every option's `summary`, render `architectureDiagram` as Mermaid when present, and show `totalMonthlyCost` plus `costItems`, then ask the user to select one. Ask even when there is only one candidate. Do not invent missing details, replace these prices with a rough estimate, or choose on the user's behalf. Return only the candidate ID/index selected by the user.
- For `deployment_confirmation`, present `solutionSummary`, `templateUrl`, the quote or explicit quote failure in `cost`, `effectiveDeploymentParameters`, `parameterOverrides`, `previewReadyForCreate`, and exactly the actions returned in `options`, then ask the user to select an action. A request to create or deploy infrastructure is not confirmation for this boundary. The bridge derives this bounded display projection directly from the Runtime's existing A2A Pipeline confirmation event; never supplement it from local Session, journal, template, spool, or tool-result files. Never confirm, adjust, reselect, or cancel on the user's behalf, including after a failed quote or Preview.
- Bind every user answer only to the current `kind`, `inputId`, `requestTaskId`, and `contextId`. Never reinterpret a resource selection as deployment confirmation or reuse it for a later input.

For an automatically decided permission, respond in one tool call while preserving the current input and tool identities:

```text
python3 scripts/iac_code.py respond --job-id <job-id> --input-id <inputId> --tool-use-id <toolUseId> --decision allow_once --follow
```

Use `deny` when the outer Agent's policy denies it. For a user question, candidate selection, or permission that was explicitly shown to the user, write the correlated answer as JSON to a UTF-8 file and resume the same job:
After the user answers, write the correlated answer as JSON to a UTF-8 file and resume the same job:

- Permission: `{"kind":"permission","requestTaskId":"<requestTaskId>","contextId":"<contextId>","inputId":"<inputId>","toolUseId":"<toolUseId>","decision":"allow_once"}` or use `deny`.
- Question: `{"kind":"ask_user_question","requestTaskId":"<requestTaskId>","contextId":"<contextId>","inputId":"<inputId>","answer":"<option, or free text only when allowed>"}`.
- Candidate: `{"kind":"candidate_selection","requestTaskId":"<requestTaskId>","contextId":"<contextId>","inputId":"<inputId>","answer":"<candidate ID or index>"}`.
- Deployment confirmation: `{"kind":"deployment_confirmation","requestTaskId":"<requestTaskId>","contextId":"<contextId>","inputId":"<inputId>","action":"<action selected by the user>","parameterOverrides":{"<parameter selected by the user>":"<value selected by the user>"}}`. Allowed actions are `confirm`, `adjust`, `reselect`, and `cancel`; omit `parameterOverrides` when the user did not request an adjustment.

```text
python3 scripts/iac_code.py respond --job-id <job-id> --input-file <answer-file> --follow
Expand Down
Loading
Loading