Skip to content

feat: agent-ready CLI substrate — adapters + contracts + EcoMap - #163

Open
atomeam wants to merge 3 commits into
feature/ci-medic-llm-integrationfrom
feat/cli-tool-adapters
Open

feat: agent-ready CLI substrate — adapters + contracts + EcoMap#163
atomeam wants to merge 3 commits into
feature/ci-medic-llm-integrationfrom
feat/cli-tool-adapters

Conversation

@atomeam

@atomeam atomeam commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a coherent CLI adapter layer for agent orchestration: four adapters (thyme, wuzz, fx, taskwarrior) with unified JSON contracts and exit codes, plus a full WSL utility layer and tool inventory.

What's in this branch

Adapters

Adapter What it wraps Proof mission
thyme Time tracking via tmux THYME-001 — lifecycle validated in isolated session
wuzz HTTP inspection tool WUZZ-001 — binary + local server test
fx JSON inspection/transform FX-001 — query + transform-preview verified
taskwarrior Task management (WSL) All commands: list, get, create, done — verified

Contracts (ADAPTER-CONTRACTS.md)

  • Consistent exit codes: 0=success, 1=usage, 2=runtime, 3=permission, 4=not-found
  • Standard JSON shapes for all adapter outputs
  • Error objects always include "error" key

WSL utility layer

jq 1.8.1, rg 15.1.0, fd 10.3.0, bat 0.25.0, fzf 0.67.0, tree, htop, task 2.6.2 — plus fd/bat shims for distro-agnostic paths.

EcoMap (integrations/ECOMAP.md)

Full inventory: 31 tools across WSL and Windows, with paths and versions.

Key decisions

  • Taskwarrior 2.6.2 expression bug worked around via jq filtering (export all, filter in jq)
  • All adapters use argument arrays — no shell interpolation
  • Production targets blocked at adapter level (wuzz gate)
  • Temp files written to system temp, cleaned up after read

No changes to main, no vendored sources, no config modifications.

atomeam added 2 commits July 18, 2026 04:26
- adapter.ps1: PowerShell entry point for Windows
- adapter-wsl.sh: Bash bridge running in WSL
- ADAPTER-CONTRACTS.md: consistent JSON shapes + exit codes for all 4 adapters
- ECOMAP.md: updated with adapter inventory
- Taskwarrior 2.6.2 expression bug worked around via jq filtering
- All commands verified: list, get, create, done
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aether-backend Error Error Jul 18, 2026 9:26am
aether-production Error Error Jul 18, 2026 9:26am

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 18, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
aether 6d5693b Jul 18 2026, 09:25 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 18, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
loxa 6d5693b Jul 18 2026, 09:25 AM

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 86202369-1634-47e2-a154-882947a9e691

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add Taskwarrior WSL adapter and document unified CLI adapter contracts

✨ Enhancement 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Add Taskwarrior adapter bridging PowerShell to WSL for clean JSON task operations
• Define cross-adapter JSON output shapes and standardized exit codes
• Record WSL/Windows tool inventory and adapter proof status in EcoMap
Diagram

graph TD
  A["Agent / Orchestrator"] --> B["taskwarrior/adapter.ps1"] --> C["wsl.exe (Ubuntu)"] --> D["taskwarrior/adapter-wsl.sh"] --> E["task CLI"] --> F["JSON stdout"]
  E --> G[("Task DB")]
  subgraph Legend
    direction LR
    _actor["Caller"] ~~~ _script["Adapter script"] ~~~ _tool["CLI tool"] ~~~ _db[("Data store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Avoid `bash -c` and pass args as an array end-to-end
  • ➕ Eliminates quoting/shell-injection hazards for descriptions/tags containing spaces or special characters
  • ➕ Matches the stated design goal of “argument arrays — no shell interpolation”
  • ➕ Makes behavior more predictable across PowerShell/WSL boundaries
  • ➖ Requires reworking the WSL invocation to avoid a single command-string
  • ➖ May need additional escaping/translation for Windows→WSL path and argument semantics
2. Centralize exit-code mapping in the PowerShell wrapper
  • ➕ Allows WSL script to focus on JSON output while PS enforces contract semantics
  • ➕ Easier to keep contract consistent across multiple WSL-backed adapters
  • ➖ PowerShell would need to parse JSON and detect not-found vs runtime errors robustly
  • ➖ Risk of double-wrapping/duplicating error handling logic
3. Use a single JSON-over-stdin adapter protocol (one process, multiple commands)
  • ➕ Reduces overhead of repeated WSL process startup
  • ➕ More structured than argv tokenization for complex filters/descriptions
  • ➖ Higher implementation complexity
  • ➖ Harder to debug manually than simple CLI commands

Recommendation: Keep the PR’s overall approach (WSL-backed adapter emitting clean JSON + documented contracts), but strongly consider adjusting the Taskwarrior wrapper to (1) avoid bash -c string composition and (2) align exit codes with ADAPTER-CONTRACTS.md (not-found should be exit 4 for get/done). Also review set -e interactions in safe_export() so error-handling paths actually execute instead of aborting the script early.

Files changed (5) +390 / -0

Enhancement (2) +150 / -0
adapter-wsl.shImplement WSL-side Taskwarrior wrapper with JSON shaping and filtering +67/-0

Implement WSL-side Taskwarrior wrapper with JSON shaping and filtering

• Adds Bash logic to export tasks, normalize fields via jq, apply a jq-based filter workaround for Taskwarrior 2.6.2, and implement get/create/done commands. Uses temp files in /tmp and emits JSON to stdout with errors on stderr.

integrations/taskwarrior/adapter-wsl.sh

adapter.ps1Add PowerShell entrypoint that validates args and invokes WSL adapter +83/-0

Add PowerShell entrypoint that validates args and invokes WSL adapter

• Adds a Windows-facing adapter that validates command/UUID inputs, selects a WSL distro, and runs the WSL Bash adapter through wsl.exe. Propagates non-zero exit codes and returns adapter output to stdout.

integrations/taskwarrior/adapter.ps1

Documentation (3) +240 / -0
ADAPTER-CONTRACTS.mdDefine adapter JSON contracts and standardized exit codes +95/-0

Define adapter JSON contracts and standardized exit codes

• Adds a single reference for adapter exit-code semantics and output shapes across thyme, wuzz, fx, and taskwarrior. Documents common patterns like UUID validation, temp-file use, and production-target gating.

integrations/ADAPTER-CONTRACTS.md

ECOMAP.mdAdd EcoMap inventory for WSL/Windows tools and adapter status +89/-0

Add EcoMap inventory for WSL/Windows tools and adapter status

• Introduces an environment inventory with binary paths and versions for Ubuntu (WSL) and local PowerShell (Windows). Records adapter locations and proof/verification status, plus deferred installations.

integrations/ECOMAP.md

README.mdDocument Taskwarrior adapter usage, JSON shape, and security notes +56/-0

Document Taskwarrior adapter usage, JSON shape, and security notes

• Adds integration docs covering prerequisites, supported commands, and an example JSON schema for tasks. Notes validation/no-interpolation intent and temp-file cleanup behavior.

integrations/taskwarrior/README.md

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (6) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 4 rules

Grey Divider


Action required

1. Bash command string injection 🐞 Bug ⛨ Security
Description
integrations/taskwarrior/adapter.ps1 builds a single bash -c string by concatenating $Command
and $Args, so spaced arguments (e.g., task descriptions) are split and metacharacters can inject
additional shell tokens. The PATH export also embeds $HOME in a PowerShell-interpolated string,
expanding it to a Windows path and breaking the intended WSL PATH.
Code

integrations/taskwarrior/adapter.ps1[R69-72]

+$WslArgs = @('-e', 'bash', '--noprofile', '--norc', '-c',
+    "export PATH=/usr/local/sbin:/usr/local/bin:$HOME/.local/bin:/usr/sbin:/usr/bin:/sbin:/bin; " +
+    "bash $AdapterSh $Command $($Args -join ' ')"
+)
Evidence
The adapter builds a bash -c string that joins user-provided args, violating the documented
"argument arrays only" rule and causing argument splitting/injection. The string also contains
$HOME inside a PowerShell double-quoted string, meaning PowerShell expands it before WSL executes
it.

integrations/taskwarrior/adapter.ps1[68-72]
integrations/ADAPTER-CONTRACTS.md[89-94]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PowerShell adapter constructs a `bash -c "..."` script that interpolates `$AdapterSh`, `$Command`, and `$Args -join ' '`, which (1) breaks argument boundaries (spaces) and (2) allows shell token injection. It also mistakenly interpolates `$HOME` on the PowerShell side, producing a Windows path in the WSL PATH export.

## Issue Context
The contract explicitly states "No shell interpolation — argument arrays only".

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[68-72]
- integrations/ADAPTER-CONTRACTS.md[89-94]

## Suggested fix
- Avoid `bash -c` for argument transport. Invoke WSL with an argument array, e.g. `wsl.exe -d $WslDistro -- bash --noprofile --norc $AdapterSh $Command @Args`.
- If you must set PATH, do it without PowerShell `$HOME` interpolation (escape `$` or set PATH via `env` with a literal WSL-side value).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Wrong WSL script path 🐞 Bug ≡ Correctness
Description
The PowerShell adapter defaults to an adapter.sh path, and the README documents adapter.sh, but
this PR only adds adapter-wsl.sh in-repo. This mismatch makes the integration fail unless users
manually override AETHER_TASK_ADAPTER_SH and/or rename/install the WSL script separately.
Code

integrations/taskwarrior/adapter.ps1[R36-39]

+$WslDistro = if ($env:AETHER_WSL_DISTRO) { $env:AETHER_WSL_DISTRO } else { 'Ubuntu' }
+$AdapterSh = if ($env:AETHER_TASK_ADAPTER_SH) { $env:AETHER_TASK_ADAPTER_SH } else {
+    '~/.local/share/aether/integrations/taskwarrior/adapter.sh'
+}
Evidence
PowerShell and README both refer to adapter.sh, while the WSL-side script added by this PR is
named adapter-wsl.sh, creating an internal inconsistency that prevents the default path from
working.

integrations/taskwarrior/adapter.ps1[36-39]
integrations/taskwarrior/README.md[53-56]
integrations/taskwarrior/adapter-wsl.sh[1-3]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The documented/expected WSL bridge script name and the shipped file name do not match (`adapter.sh` vs `adapter-wsl.sh`). The PowerShell adapter’s default path and README both reference `adapter.sh`, but the repo contains only `adapter-wsl.sh`.

## Issue Context
This breaks out-of-the-box execution and makes the integration dependent on undocumented manual setup.

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[36-39]
- integrations/taskwarrior/README.md[53-56]
- integrations/taskwarrior/adapter-wsl.sh[1-3]

## Suggested fix
Choose one:
- Rename `adapter-wsl.sh` to `adapter.sh` and update docs accordingly, or
- Update `adapter.ps1` default + README to refer to `adapter-wsl.sh`, and document/provide an install step that places it in the expected WSL location.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Not-found exit codes wrong 🐞 Bug ≡ Correctness
Description
integrations/taskwarrior/adapter-wsl.sh does not exit with code 4 when a UUID is missing: get
returns a not-found object but still exits 0, and done exits 1. This violates
ADAPTER-CONTRACTS.md and breaks callers that use exit code 4 to distinguish missing UUIDs from
success/usage errors.
Code

integrations/taskwarrior/adapter-wsl.sh[R34-38]

+cmd_get() {
+    local uuid="$1"; [ -z "$uuid" ] && echo '{"error":"uuid required"}' >&2 && exit 1
+    local t; t=$(safe_export "") || return 1
+    jq "map(select(.uuid == \"$uuid\"))[0] // {\"error\":\"not found\",\"uuid\":\"$uuid\"}" "$t"
+    rm -f "$t"
Evidence
The WSL script’s get path always exits 0 even when it returns {error:"not found"}, and the
done path explicitly exits 1 on missing UUID. The contract section for Taskwarrior requires exit 4
for not found in both get and done.

integrations/taskwarrior/adapter-wsl.sh[34-38]
integrations/taskwarrior/adapter-wsl.sh[51-56]
integrations/ADAPTER-CONTRACTS.md[69-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Taskwarrior adapter contract requires exit code 4 for not-found UUIDs. The current WSL adapter returns 0 for `get` not-found (because `jq` succeeds) and returns 1 for `done` not-found.

## Issue Context
This violates the standardized adapter exit-code semantics documented in `integrations/ADAPTER-CONTRACTS.md`.

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[34-39]
- integrations/taskwarrior/adapter-wsl.sh[51-57]
- integrations/ADAPTER-CONTRACTS.md[69-80]

## Suggested fix
- In `cmd_get`, detect the not-found case and `exit 4` after emitting the JSON error object.
- In `cmd_done`, replace `exit 1` with `exit 4` for missing UUIDs.
- Ensure the error object is emitted consistently with your stderr/stdout policy.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Runtime errors become usage 🐞 Bug ☼ Reliability
Description
When safe_export fails, multiple commands coerce the failure into return code 1 via || return 1,
masking runtime/tool failures as usage errors. This violates the contract’s exit code 2 semantics
for runtime errors and can cause incorrect retry/diagnosis behavior.
Code

integrations/taskwarrior/adapter-wsl.sh[R30-33]

+cmd_list() {
+    local filter="${*:-}"; local t; t=$(safe_export "") || return 1
+    local f; f=$(apply_filter "$t" "$filter"); clean_task "$f"; rm -f "$f" "$t"
+}
Evidence
The command handlers explicitly convert safe_export failures into code 1, while the contract
requires code 2 for runtime errors like export/add failures.

integrations/taskwarrior/adapter-wsl.sh[30-33]
integrations/ADAPTER-CONTRACTS.md[11-15]
integrations/ADAPTER-CONTRACTS.md[69-73]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`safe_export` can fail due to Taskwarrior/tool/runtime problems, but callers commonly do `t=$(safe_export ...) || return 1`, which forces a usage error code instead of the contract’s runtime error code.

## Issue Context
Contract defines:
- 1 = usage
- 2 = runtime/tool failure

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[30-33]
- integrations/taskwarrior/adapter-wsl.sh[40-43]
- integrations/taskwarrior/adapter-wsl.sh[44-49]
- integrations/taskwarrior/adapter-wsl.sh[51-54]
- integrations/ADAPTER-CONTRACTS.md[11-15]

## Suggested fix
- Replace `|| return 1` with `|| return 2` (or a helper that maps tool failures to 2).
- Consider standardizing: `safe_export` emits JSON error + returns 2, and callers propagate 2 without rewriting it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Done stderr leaks to stdout 🐞 Bug ☼ Reliability
Description
cmd_done uses redirections 2>&1 >/dev/null, which can leak Taskwarrior stderr into stdout and
corrupt JSON-only output. The call also lacks explicit error mapping (e.g., emitting a JSON error
and exiting 2) if task done fails for reasons other than set -e termination.
Code

integrations/taskwarrior/adapter-wsl.sh[R56-57]

+    $TASK_BIN "$id" done 2>&1 >/dev/null
+    echo "{\"uuid\":\"$uuid\",\"id\":$id,\"status\":\"completed\",\"action\":\"done\"}"
Evidence
The redirection 2>&1 is applied before redirecting stdout to /dev/null, so stderr can still flow
to the original stdout stream. This risks mixing non-JSON text into adapter output.

integrations/taskwarrior/adapter-wsl.sh[51-57]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The stderr/stdout redirection order is incorrect, so stderr may still reach the caller even when stdout is discarded. This can break consumers expecting valid JSON on stdout.

## Issue Context
The adapter contract emphasizes consistent machine-consumable output.

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[51-57]

## Suggested fix
- Change to `>/dev/null 2>&1` (if the goal is to suppress all output from `task done`).
- Wrap the call to capture status and, on failure, emit `{ "error": "done failed", "code": <rc> }` and exit 2 (runtime).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Non-JSON PowerShell errors 🐞 Bug ≡ Correctness
Description
The PowerShell adapter emits plain Write-Error strings for usage and runtime errors, rather than a
JSON error object with an error key as required by the adapter contract. This makes error handling
inconsistent and can break JSON-only consumers.
Code

integrations/taskwarrior/adapter.ps1[R52-57]

+            Write-Error "Usage: adapter.ps1 $Command <uuid>"
+            exit 1
+        }
+        if ($Args[0] -notmatch '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
+            Write-Error "Invalid UUID format: $($Args[0])"
+            exit 1
Evidence
The adapter contract states errors include an error key, but the PowerShell adapter’s error paths
produce plain text error messages via Write-Error instead of JSON.

integrations/taskwarrior/adapter.ps1[41-46]
integrations/taskwarrior/adapter.ps1[48-58]
integrations/taskwarrior/adapter.ps1[78-81]
integrations/ADAPTER-CONTRACTS.md[89-94]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The contract requires errors to include an `error` key, but the PowerShell adapter outputs non-JSON error records/messages (`Write-Error "Usage: ..."`, and `Write-Error "...: $result"`).

## Issue Context
Downstream agent tooling typically expects machine-readable JSON on failures too.

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[41-46]
- integrations/taskwarrior/adapter.ps1[48-66]
- integrations/taskwarrior/adapter.ps1[78-81]
- integrations/ADAPTER-CONTRACTS.md[89-94]

## Suggested fix
- Replace `Write-Error` messages with JSON error objects written to stderr (e.g., `[Console]::Error.WriteLine('{"error":"..."}')`) and exit with the appropriate code.
- On WSL nonzero exit, forward the WSL stderr as-is (without wrapping) or wrap it into a JSON error object while preserving the exit code.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +69 to +72
$WslArgs = @('-e', 'bash', '--noprofile', '--norc', '-c',
"export PATH=/usr/local/sbin:/usr/local/bin:$HOME/.local/bin:/usr/sbin:/usr/bin:/sbin:/bin; " +
"bash $AdapterSh $Command $($Args -join ' ')"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Bash command string injection 🐞 Bug ⛨ Security

integrations/taskwarrior/adapter.ps1 builds a single bash -c string by concatenating $Command
and $Args, so spaced arguments (e.g., task descriptions) are split and metacharacters can inject
additional shell tokens. The PATH export also embeds $HOME in a PowerShell-interpolated string,
expanding it to a Windows path and breaking the intended WSL PATH.
Agent Prompt
## Issue description
The PowerShell adapter constructs a `bash -c "..."` script that interpolates `$AdapterSh`, `$Command`, and `$Args -join ' '`, which (1) breaks argument boundaries (spaces) and (2) allows shell token injection. It also mistakenly interpolates `$HOME` on the PowerShell side, producing a Windows path in the WSL PATH export.

## Issue Context
The contract explicitly states "No shell interpolation — argument arrays only".

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[68-72]
- integrations/ADAPTER-CONTRACTS.md[89-94]

## Suggested fix
- Avoid `bash -c` for argument transport. Invoke WSL with an argument array, e.g. `wsl.exe -d $WslDistro -- bash --noprofile --norc $AdapterSh $Command @Args`.
- If you must set PATH, do it without PowerShell `$HOME` interpolation (escape `$` or set PATH via `env` with a literal WSL-side value).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +36 to +39
$WslDistro = if ($env:AETHER_WSL_DISTRO) { $env:AETHER_WSL_DISTRO } else { 'Ubuntu' }
$AdapterSh = if ($env:AETHER_TASK_ADAPTER_SH) { $env:AETHER_TASK_ADAPTER_SH } else {
'~/.local/share/aether/integrations/taskwarrior/adapter.sh'
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Wrong wsl script path 🐞 Bug ≡ Correctness

The PowerShell adapter defaults to an adapter.sh path, and the README documents adapter.sh, but
this PR only adds adapter-wsl.sh in-repo. This mismatch makes the integration fail unless users
manually override AETHER_TASK_ADAPTER_SH and/or rename/install the WSL script separately.
Agent Prompt
## Issue description
The documented/expected WSL bridge script name and the shipped file name do not match (`adapter.sh` vs `adapter-wsl.sh`). The PowerShell adapter’s default path and README both reference `adapter.sh`, but the repo contains only `adapter-wsl.sh`.

## Issue Context
This breaks out-of-the-box execution and makes the integration dependent on undocumented manual setup.

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[36-39]
- integrations/taskwarrior/README.md[53-56]
- integrations/taskwarrior/adapter-wsl.sh[1-3]

## Suggested fix
Choose one:
- Rename `adapter-wsl.sh` to `adapter.sh` and update docs accordingly, or
- Update `adapter.ps1` default + README to refer to `adapter-wsl.sh`, and document/provide an install step that places it in the expected WSL location.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +34 to +38
cmd_get() {
local uuid="$1"; [ -z "$uuid" ] && echo '{"error":"uuid required"}' >&2 && exit 1
local t; t=$(safe_export "") || return 1
jq "map(select(.uuid == \"$uuid\"))[0] // {\"error\":\"not found\",\"uuid\":\"$uuid\"}" "$t"
rm -f "$t"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Not-found exit codes wrong 🐞 Bug ≡ Correctness

integrations/taskwarrior/adapter-wsl.sh does not exit with code 4 when a UUID is missing: get
returns a not-found object but still exits 0, and done exits 1. This violates
ADAPTER-CONTRACTS.md and breaks callers that use exit code 4 to distinguish missing UUIDs from
success/usage errors.
Agent Prompt
## Issue description
The Taskwarrior adapter contract requires exit code 4 for not-found UUIDs. The current WSL adapter returns 0 for `get` not-found (because `jq` succeeds) and returns 1 for `done` not-found.

## Issue Context
This violates the standardized adapter exit-code semantics documented in `integrations/ADAPTER-CONTRACTS.md`.

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[34-39]
- integrations/taskwarrior/adapter-wsl.sh[51-57]
- integrations/ADAPTER-CONTRACTS.md[69-80]

## Suggested fix
- In `cmd_get`, detect the not-found case and `exit 4` after emitting the JSON error object.
- In `cmd_done`, replace `exit 1` with `exit 4` for missing UUIDs.
- Ensure the error object is emitted consistently with your stderr/stdout policy.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +30 to +33
cmd_list() {
local filter="${*:-}"; local t; t=$(safe_export "") || return 1
local f; f=$(apply_filter "$t" "$filter"); clean_task "$f"; rm -f "$f" "$t"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Runtime errors become usage 🐞 Bug ☼ Reliability

When safe_export fails, multiple commands coerce the failure into return code 1 via || return 1,
masking runtime/tool failures as usage errors. This violates the contract’s exit code 2 semantics
for runtime errors and can cause incorrect retry/diagnosis behavior.
Agent Prompt
## Issue description
`safe_export` can fail due to Taskwarrior/tool/runtime problems, but callers commonly do `t=$(safe_export ...) || return 1`, which forces a usage error code instead of the contract’s runtime error code.

## Issue Context
Contract defines:
- 1 = usage
- 2 = runtime/tool failure

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[30-33]
- integrations/taskwarrior/adapter-wsl.sh[40-43]
- integrations/taskwarrior/adapter-wsl.sh[44-49]
- integrations/taskwarrior/adapter-wsl.sh[51-54]
- integrations/ADAPTER-CONTRACTS.md[11-15]

## Suggested fix
- Replace `|| return 1` with `|| return 2` (or a helper that maps tool failures to 2).
- Consider standardizing: `safe_export` emits JSON error + returns 2, and callers propagate 2 without rewriting it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +56 to +57
$TASK_BIN "$id" done 2>&1 >/dev/null
echo "{\"uuid\":\"$uuid\",\"id\":$id,\"status\":\"completed\",\"action\":\"done\"}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

5. Done stderr leaks to stdout 🐞 Bug ☼ Reliability

cmd_done uses redirections 2>&1 >/dev/null, which can leak Taskwarrior stderr into stdout and
corrupt JSON-only output. The call also lacks explicit error mapping (e.g., emitting a JSON error
and exiting 2) if task done fails for reasons other than set -e termination.
Agent Prompt
## Issue description
The stderr/stdout redirection order is incorrect, so stderr may still reach the caller even when stdout is discarded. This can break consumers expecting valid JSON on stdout.

## Issue Context
The adapter contract emphasizes consistent machine-consumable output.

## Fix Focus Areas
- integrations/taskwarrior/adapter-wsl.sh[51-57]

## Suggested fix
- Change to `>/dev/null 2>&1` (if the goal is to suppress all output from `task done`).
- Wrap the call to capture status and, on failure, emit `{ "error": "done failed", "code": <rc> }` and exit 2 (runtime).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +52 to +57
Write-Error "Usage: adapter.ps1 $Command <uuid>"
exit 1
}
if ($Args[0] -notmatch '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
Write-Error "Invalid UUID format: $($Args[0])"
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. Non-json powershell errors 🐞 Bug ≡ Correctness

The PowerShell adapter emits plain Write-Error strings for usage and runtime errors, rather than a
JSON error object with an error key as required by the adapter contract. This makes error handling
inconsistent and can break JSON-only consumers.
Agent Prompt
## Issue description
The contract requires errors to include an `error` key, but the PowerShell adapter outputs non-JSON error records/messages (`Write-Error "Usage: ..."`, and `Write-Error "...: $result"`).

## Issue Context
Downstream agent tooling typically expects machine-readable JSON on failures too.

## Fix Focus Areas
- integrations/taskwarrior/adapter.ps1[41-46]
- integrations/taskwarrior/adapter.ps1[48-66]
- integrations/taskwarrior/adapter.ps1[78-81]
- integrations/ADAPTER-CONTRACTS.md[89-94]

## Suggested fix
- Replace `Write-Error` messages with JSON error objects written to stderr (e.g., `[Console]::Error.WriteLine('{"error":"..."}')`) and exit with the appropriate code.
- On WSL nonzero exit, forward the WSL stderr as-is (without wrapping) or wrap it into a JSON error object while preserving the exit code.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant