diff --git a/.changeset/agent-ok-preflight.md b/.changeset/agent-ok-preflight.md index 0fb4b673..9dd0c5a7 100644 --- a/.changeset/agent-ok-preflight.md +++ b/.changeset/agent-ok-preflight.md @@ -2,4 +2,4 @@ "@taskless/cli": patch --- -New `taskless agent ok` topic: it prints one line confirming the CLI can run, through the invocation it was launched with, and does nothing else. The Taskless skill and the `/tskl` command now run it once per session before any other Taskless command, so a harness that blocks download-and-run commands (Claude Code's auto mode, for one) stops the agent before it starts work rather than partway through. On a blocked command the agent now names the exact command to the user, offers to have them approve it, run it themselves with `!`, or allow exactly that invocation, and never proposes an allow rule that wildcards the package name or version. +New `taskless agent ok` topic: it prints one line confirming the CLI can run, through the invocation it was launched with, and does nothing else. The Taskless skill and the `/tskl` command now run it once per session before any other Taskless command, so a harness that blocks download-and-run commands (Claude Code's auto mode, for one) stops the agent before it starts work rather than partway through. On a blocked command the agent now names the exact command to the user, offers three ways forward (an allow rule for exactly that invocation, approval through the agent's permissions command such as `/permissions`, or approving every Taskless command by hand in chat), and never proposes an allow rule that wildcards the package name or version. diff --git a/commands/tskl/tskl.md b/commands/tskl/tskl.md index 85ee2a6b..4bed0390 100644 --- a/commands/tskl/tskl.md +++ b/commands/tskl/tskl.md @@ -24,10 +24,13 @@ Otherwise, follow the same flow as the `taskless` skill: line. If the harness or the user blocks it, or blocks any later Taskless command, stop and do not try to get around the block. Tell the user the exact command and that it downloads and runs a package from npm, then - offer: they approve that exact command in their reply, they run it - themselves as `! `, or you add an allow rule for exactly - the invocation `%(TASKLESS_CLI)s`. Never propose a rule wider than that - invocation, such as a wildcard over the package name or its version. + offer three ways forward and wait for their choice: you add an allow rule + for exactly the invocation `%(TASKLESS_CLI)s` to the agent's permission + settings, they approve it through their agent's permissions command + (such as `/permissions` in Claude Code), or they approve every Taskless + command manually, here in chat, as you run it. Never propose a rule wider + than that invocation, such as a wildcard over the package name or its + version. 1. Identify the topic from `$ARGUMENTS` using the table below. 2. Fetch the canonical recipe with `%(TASKLESS_CLI)s agent ` (or `%(TASKLESS_CLI)s agent --anonymous` if the user is offline or diff --git a/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/proposal.md b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/proposal.md new file mode 100644 index 00000000..312730df --- /dev/null +++ b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/proposal.md @@ -0,0 +1,30 @@ +## Why + +The first real blocked preflight showed the remedies are the wrong set. Claude Code's auto mode refused `npx @taskless/cli-nightly@ agent ok`, and the agent offered what the skill told it to: approve that one command in chat, run it yourself as `! `, or add an exact-invocation allow rule. + +Two of those only unblock the preflight. `!` runs `agent ok` once and leaves every later Taskless command as blocked as before, so the user has done work for a check that proves nothing about the next call. Approving "that exact command" has the same shape. Meanwhile the remedy a user is most likely to reach for, their agent's own permissions command, is not mentioned at all. + +## What Changes + +- The blocked-preflight guidance offers three ways forward, and the agent waits for the user's choice: + 1. The agent adds an allow rule for exactly the invocation the skill names to the agent's permission settings. + 2. The user approves it through their agent's permissions command, such as `/permissions` in Claude Code. + 3. The user approves every Taskless command manually, in chat, as the agent runs it. +- The `! ` route is dropped. +- Unchanged: stop before any work, name the exact command and that it downloads a package from npm, and never propose a rule wider than the invocation. + +## Delivery shape + +**Single PR.** Two skill-body paragraphs, one test, one spec delta, and a changeset edit. + +## Capabilities + +### Modified Capabilities + +- `skill-taskless`: the blocked-preflight remedies. + +## Impact + +- `skills/taskless/SKILL.md`, `commands/tskl/tskl.md`: the remedy list. +- `packages/cli/test/installed-documentation.test.ts`: asserts the new remedies and the absence of the `!` route. +- `.changeset/agent-ok-preflight.md`: still unreleased, so its description is corrected in place rather than adding a second changeset. diff --git a/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/specs/skill-taskless/spec.md b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/specs/skill-taskless/spec.md new file mode 100644 index 00000000..22e1dff3 --- /dev/null +++ b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/specs/skill-taskless/spec.md @@ -0,0 +1,25 @@ +## MODIFIED Requirements + +### Requirement: Skill preflights the CLI before the first Taskless command + +The skill body and the `tskl` command body SHALL instruct the agent to run `%(TASKLESS_CLI)s agent ok` once per session, before any other Taskless command, and to proceed only once it prints its confirmation line. + +When the preflight is blocked by the harness or the user, the bodies SHALL instruct the agent to: + +1. Stop before doing any Taskless work, and not attempt to work around the block. +2. Tell the user the exact command, and that it downloads and runs a package from npm. +3. Offer the user three ways forward, and wait for their choice: the agent adds an allow rule for exactly the invocation the skill names to the agent's permission settings; the user approves it through their agent's permissions command, such as `/permissions` in Claude Code; or the user approves every Taskless command manually, in chat, as the agent runs it. +4. Never propose an allow rule that widens the invocation, such as a wildcard over the package name or its version. + +#### Scenario: Skill body runs the preflight first + +- **WHEN** the skill body or the `tskl` command body is read from source +- **THEN** it SHALL instruct the agent to run `%(TASKLESS_CLI)s agent ok` before any other Taskless command in the session + +#### Scenario: Skill body handles a blocked preflight + +- **WHEN** the skill body or the `tskl` command body is read from source +- **THEN** it SHALL instruct the agent, on a blocked preflight, to stop and name the exact command to the user +- **AND** SHALL offer an allow rule for the exact invocation, the agent's permissions command, and per-command approval in chat +- **AND** SHALL NOT offer running the command with `!`, which unblocks only the preflight +- **AND** SHALL forbid an allow rule that wildcards the package name or version diff --git a/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/tasks.md b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/tasks.md new file mode 100644 index 00000000..707e8143 --- /dev/null +++ b/openspec/changes/archive/2026-10-15-blocked-preflight-remedies/tasks.md @@ -0,0 +1,7 @@ +## 1. Remedies + +- [x] 1.1 Replace the remedy list in `skills/taskless/SKILL.md` with the allow rule, the permissions command, and per-command chat approval; drop `!` +- [x] 1.2 Make the same change in `commands/tskl/tskl.md` +- [x] 1.3 Update the preflight test to assert the three remedies and the absence of `! ` +- [x] 1.4 Correct the pending `agent-ok-preflight` changeset +- [x] 1.5 Run `pnpm typecheck` and `pnpm lint` diff --git a/openspec/specs/skill-taskless/spec.md b/openspec/specs/skill-taskless/spec.md index 37a15c39..e9e3613e 100644 --- a/openspec/specs/skill-taskless/spec.md +++ b/openspec/specs/skill-taskless/spec.md @@ -191,7 +191,7 @@ When the preflight is blocked by the harness or the user, the bodies SHALL instr 1. Stop before doing any Taskless work, and not attempt to work around the block. 2. Tell the user the exact command, and that it downloads and runs a package from npm. -3. Offer the user ways forward: approve that exact command in their reply, run `! ` themselves, or have the agent add an allow rule for exactly the invocation the skill names. +3. Offer the user three ways forward, and wait for their choice: the agent adds an allow rule for exactly the invocation the skill names to the agent's permission settings; the user approves it through their agent's permissions command, such as `/permissions` in Claude Code; or the user approves every Taskless command manually, in chat, as the agent runs it. 4. Never propose an allow rule that widens the invocation, such as a wildcard over the package name or its version. #### Scenario: Skill body runs the preflight first @@ -203,5 +203,6 @@ When the preflight is blocked by the harness or the user, the bodies SHALL instr - **WHEN** the skill body or the `tskl` command body is read from source - **THEN** it SHALL instruct the agent, on a blocked preflight, to stop and name the exact command to the user -- **AND** SHALL offer both the `!` route and an allow rule for the exact invocation +- **AND** SHALL offer an allow rule for the exact invocation, the agent's permissions command, and per-command approval in chat +- **AND** SHALL NOT offer running the command with `!`, which unblocks only the preflight - **AND** SHALL forbid an allow rule that wildcards the package name or version diff --git a/packages/cli/test/installed-documentation.test.ts b/packages/cli/test/installed-documentation.test.ts index 0f59bbcb..de355732 100644 --- a/packages/cli/test/installed-documentation.test.ts +++ b/packages/cli/test/installed-documentation.test.ts @@ -209,10 +209,15 @@ describe("this repository's own installed Taskless docs", () => { const prose = body.replaceAll(/\s+/g, " "); expect(prose, name).toContain("%(TASKLESS_CLI)s agent ok"); expect(prose, name).toContain("before any other Taskless command"); - expect(prose, name).toContain("! "); expect(prose, name).toContain( "allow rule for exactly the invocation `%(TASKLESS_CLI)s`" ); + expect(prose, name).toContain("`/permissions`"); + expect(prose, name).toContain( + "approve every Taskless command manually, here in chat" + ); + // `!` runs the preflight once and leaves every later command blocked. + expect(prose, name).not.toContain("! "); expect(prose, name).toContain("wildcard over the package name"); } }); diff --git a/skills/taskless/SKILL.md b/skills/taskless/SKILL.md index 21d125f3..6576856e 100644 --- a/skills/taskless/SKILL.md +++ b/skills/taskless/SKILL.md @@ -43,11 +43,14 @@ confirming the invocation works. Proceed once you see it. If the harness or the user blocks it, or blocks any later Taskless command, stop before doing any Taskless work and do not try to get around the block. Tell the user the exact command you ran, and that it downloads and runs a -package from npm. Then offer the ways forward: - -- They approve that exact command in their reply. -- They run it themselves as `! `, so its output lands here. -- You add an allow rule for exactly the invocation `%(TASKLESS_CLI)s`. +package from npm. Then offer these three ways forward, and wait for their +choice: + +- You add an allow rule for exactly the invocation `%(TASKLESS_CLI)s` to the + agent's permission settings. +- They approve it through their agent's permissions command, such as + `/permissions` in Claude Code. +- They approve every Taskless command manually, here in chat, as you run it. Never propose a rule wider than that invocation, such as a wildcard over the package name or its version: it would approve a CLI this project never