Repository navigation
feat(init): carry Taskless trust into Claude Code's auto mode, one Taskless rule per permission file - #522
Conversation
|
@claude /review |
|
Claude finished @theCodeDrift's task in 6m 59s —— View job Review completeReview mode: incremental — read 0 prior review thread(s) before reviewing.
Summary: This is a well-scoped, carefully-tested change. I traced the core logic change in Three [New] findings, all non-blocking:
Nothing else stood out across correctness, security, or test coverage — the global-trust write path correctly avoids home-directory I/O in non-interactive/batch mode, re-validates before writing rather than trusting a stale preview, and the skill body's embedded entry text is pinned byte-for-byte to |
All three findings were addressed in 938adea: Codex files are recognised by a fixed — AI Coding Agent |
Claude Code's auto mode refused
npx @taskless/cli-nightly@<version> info --jsonduring onboarding as "Code from External", even though.claude/settings.jsonallowed that exact invocation. The classifier overrules project allow rules for downloaded code, and it reads its own exceptions (autoMode) only from user settings, never from a checked-in project file, so nothinginitwrites into the repo can clear it. The user already made that trust decision when they ran the installer; this carries it into the session from the one place the classifier reads.What changes
initremoves every Taskless allow rule (@taskless/clior@taskless/cli-nightly, any version, recorded or not, including theBash(<invocation>:*)form the skill used to propose) and writes the installed version's. Each removal shows asREMOVE:. Deny rules and other packages' rules are untouched. This replaces the spec's "a rule you wrote is never touched": a pinned rule for a version that is no longer installed allows nothing anyone wants.npx @taskless/cliwith no arguments) lists every settings edit together, as alignedALLOW (project):/REMOVE (project):/ALLOW (global):statements wrapped to 76 columns, under one question, "Make these changes to your settings?", and on yes adds the entry to top-levelautoMode.allowin~/.claude/settings.json(honouringCLAUDE_CONFIG_DIR). It names no version and states that a call is covered only when it names an exact version. It is seeded after"$defaults"wheninitcreates the list, found later by itsTaskless CLI:label, never rewritten, offered again on every wizard run that does not find it, and never recorded in the repo manifest. Behind a closed per-harness list, so Codex can join once its guardian review is verified.initnever writes outside the project. It reads the entry, warns when it is missing (file, key, and text), and reports it underglobalTrustin--json.SKILL.mdtells the agent to stop without retrying and hand the user the entry inline, which a test keeps identical to the code's copy. It cannot point at anagent <topic>recipe, since that is fetched through the same refusednpx.Size. About 1,300 hand-written lines (the remaining ~400 are the archive's copy of the specs). It ships as one PR because the warning, the wizard offer, and the skill fallback all hand over the same entry, and splitting them would ship a warning that points at an offer that does not exist yet.
Checks.
pnpm typecheck,pnpm lint, and the CLI suite (2,370 tests) pass.openspec validate --strictpasses; an archive dry run lost only the intentionally reversed scenario "A user's own rule survives an upgrade". The old cli-init requirement is a REMOVED plus an ADDED, because OpenSpec 1.12 refuses a MODIFIED that drops a scenario, and its title would have been false afterwards.Follow-up (not a merge gate): in a scratch repo under Claude Code auto mode, with the entry in
~/.claude/settings.json, run onboarding and record whetherinfo --jsonis still refused. The entry is guidance to a model, not a switch, so this is the only evidence that it lands.