fix(agent): handle reasoning tags for #248 - #249
Conversation
📝 WalkthroughWalkthroughAdds audited Bash workflows for OpenHermit gateway chat, phone-agent interaction, and work-task tracking. A JSONL ledger records session, agent, task, invoice, and verification events. ChangesAudited agent workflows
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant OpenHermit
participant AgentScripts
participant Veilpiercer
Operator->>AgentScripts: start audited workflow
AgentScripts->>OpenHermit: start gateway or chat
OpenHermit-->>AgentScripts: provide chat interaction
AgentScripts->>Veilpiercer: log session and agent events
AgentScripts->>Veilpiercer: verify audit ledger
Veilpiercer-->>Operator: verification result
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment Warning |
There was a problem hiding this comment.
Actionable comments posted: 16
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.veilpiercer.jsonl:
- Around line 11-17: Prevent raw runtime messages from being committed by moving
the .veilpiercer.jsonl ledger outside the repository or sanitizing it to retain
only allowlisted fields, and add the runtime file pattern to .gitignore.
Preserve necessary audit metadata such as timestamps, event types, and hashes
without persisting complete USER_MSG or AGENT_RESPONSE content.
In `@phone-agent.sh`:
- Around line 8-16: Update the interactive loop around `AGENT_END` and
`veilpiercer verify` by adding an idempotent cleanup function and registering it
with traps for Ctrl-C, SIGTERM, and related termination signals. Ensure cleanup
logs the session end, runs audit verification once, and preserves or propagates
verification failures across both typed `exit` and interrupted termination
paths.
- Line 6: Update the audit command invocations in phone-agent.sh, including the
AGENT_START log and the additional veilpiercer log/verify calls, to check each
command’s exit status. Immediately terminate with a nonzero status when any
audit operation fails, ensuring the script cannot continue or report successful
verification after a failure.
- Around line 23-24: Update the USER_MSG logging in the message-processing flow
to avoid persisting raw phone-message content; replace the sanitized message
payload with the approved redaction, metadata, or digest mechanism. Do not rely
on quote removal or truncation as privacy protection, and preserve the existing
count/context information in veilpiercer log.
- Around line 8-10: Update the input loop around the read command to use IFS=
read -r -p "You: " msg and check its return status before processing msg. On
EOF, route execution through the existing normal cleanup path instead of logging
or appending another USER_MSG event; preserve the current exit-command handling
for valid input.
In `@start-hermit-audit.sh`:
- Line 12: Replace the predictable /tmp/gateway.log path in the background
start:gateway command with a log file created via mktemp, retain its path for
subsequent use, and remove the temporary log during the script’s cleanup
handling.
- Around line 18-23: The readiness probe in the loop using curl against
/api/agents must validate an actual successful gateway response rather than
merely a completed HTTP request. Replace the protected endpoint with a public
health endpoint or provide the required authorization, enable HTTP failure
detection, and add connection and overall request timeouts before logging
GATEWAY_READY.
- Around line 48-52: Preserve nonzero chat and verification exits across both
audit wrappers. In start-hermit-audit.sh, replace the hermit chat || true flow
with status capture, log a failure or abort outcome instead of unconditional
CHAT_END success, perform cleanup, and exit nonzero. In run-with-audit.sh,
capture chat and verification statuses, use an EXIT trap to record lifecycle
completion, and propagate any failure; update both referenced sites accordingly.
- Around line 12-14: Add an EXIT trap immediately after assigning GATEWAY_PID
that terminates the gateway, waits for its completion, and cleans up on normal
exits, errors, or signals. Apply the same cleanup behavior to the later gateway
startup block around the second GATEWAY_PID assignment, preserving the existing
straight-line flow.
In `@work-agent.sh`:
- Line 20: Update the command dispatch case for time so it accepts the
documented task argument, including prompts with spaces, and passes that task to
the timing workflow. Keep the help text and existing behavior for other commands
unchanged.
- Around line 29-35: Update the time command handling to check for an existing
active timer before writing .current_task or .task_start_time. If a timer is
active, refuse to start the new task and leave the existing timer state
unchanged; otherwise preserve the current task initialization, TASK_STARTED
logging, and timing output.
- Line 49: Update the task persistence and parsing around the work_tasks.csv
append and the awk processing near line 72 so task names containing commas
cannot shift the duration field. Use a CSV-aware serializer/parser or replace
the internal format with a validated unambiguous delimiter, and ensure invoice
totals continue reading the actual MINS value.
- Line 11: Update work-agent.sh so failures from both veilpiercer log and
veilpiercer verify propagate as nonzero exits instead of being ignored. Remove
or defer the exit success message until after veilpiercer verify completes
successfully, and report success only on that successful verification path.
- Line 14: Update both interactive input reads in work-agent.sh to use IFS= read
-r -p, preserving literal backslashes in command and task-name values before
they are written to .current_task, work_tasks.csv, and veilpiercer logs.
- Line 14: Update the command-reading loop around read in the work-agent script
to detect EOF or another failed read, then route through the existing
WORK_AGENT_END/session-finalization path so verification and cleanup still run
before exiting. Preserve normal command handling for successful reads and ensure
the EOF path terminates with the appropriate exit status after finalization.
- Around line 32-33: Update work-agent.sh to create and use a private,
permission-restricted state directory for temporary files such as .current_task
and .task_start_time, rather than writing predictable paths in the caller’s
working directory. Also change the work_tasks.csv append logic to resolve the
file from the script’s installed canonical location instead of the current
working directory.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: cf99ccf8-f6b8-4f51-8c8f-394e403d8510
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (5)
.veilpiercer.jsonlphone-agent.shrun-with-audit.shstart-hermit-audit.shwork-agent.sh
| {"timestamp": "2026-07-26T20:12:42.292029+00:00", "event": "USER_MSG", "message": "[1] what can we do", "prev_hash": "b91516160c629a5b58218c3f99a1e14ba8c5266881106015788b4210d7e1699b", "hash": "3a35c9ff6a77e1949750b89ee9dfd0d530fe74354ddd64fd6b0ef0838abcdc59"} | ||
| {"timestamp": "2026-07-26T20:12:42.383690+00:00", "event": "AGENT_RESPONSE", "message": "Response #1", "prev_hash": "3a35c9ff6a77e1949750b89ee9dfd0d530fe74354ddd64fd6b0ef0838abcdc59", "hash": "cd6a7f4f690ce3b37dfe3e6697a692159bc142789c3d5ed3bd884135be4ea4c5"} | ||
| {"timestamp": "2026-07-26T20:12:51.750472+00:00", "event": "USER_MSG", "message": "[2] cd ~/openhermit", "prev_hash": "cd6a7f4f690ce3b37dfe3e6697a692159bc142789c3d5ed3bd884135be4ea4c5", "hash": "24aa07350026576b1ea6462102435a15e58fb45a48cd6086eededb0b036572fa"} | ||
| {"timestamp": "2026-07-26T20:12:51.838487+00:00", "event": "AGENT_RESPONSE", "message": "Response #2", "prev_hash": "24aa07350026576b1ea6462102435a15e58fb45a48cd6086eededb0b036572fa", "hash": "b3353c69175d479c62769af4b2635d3045c6c5ad2493fac7ba8f93a1137a5811"} | ||
| {"timestamp": "2026-07-26T20:12:51.950403+00:00", "event": "USER_MSG", "message": "[3] ", "prev_hash": "b3353c69175d479c62769af4b2635d3045c6c5ad2493fac7ba8f93a1137a5811", "hash": "ca6ae05ca1e9335329e0884213c2f7186db8432a4d6d1342dfc61226b37f1d06"} | ||
| {"timestamp": "2026-07-26T20:12:52.044142+00:00", "event": "AGENT_RESPONSE", "message": "Response #3", "prev_hash": "ca6ae05ca1e9335329e0884213c2f7186db8432a4d6d1342dfc61226b37f1d06", "hash": "01923ebe660007780a850b54fb752b2d417d38c8f47648200d762e8a5b9dfec6"} | ||
| {"timestamp": "2026-07-26T20:12:52.140421+00:00", "event": "USER_MSG", "message": "[4] cat > phone-agent.sh << 'EOF'", "prev_hash": "01923ebe660007780a850b54fb752b2d417d38c8f47648200d762e8a5b9dfec6", "hash": "e0dd0c7543bedc188bd7f48ad455f0b88e7ba7cea97b2620f095681355737ecb"} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Keep raw runtime messages out of the repository.
These USER_MSG records persist complete user input—including shell commands and local paths. Future prompts could contain credentials or PII, which would then remain in Git history. Store the ledger outside the repository or redact/allowlist message fields, and add the runtime file to .gitignore.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.veilpiercer.jsonl around lines 11 - 17, Prevent raw runtime messages from
being committed by moving the .veilpiercer.jsonl ledger outside the repository
or sanitizing it to retain only allowlisted fields, and add the runtime file
pattern to .gitignore. Preserve necessary audit metadata such as timestamps,
event types, and hashes without persisting complete USER_MSG or AGENT_RESPONSE
content.
| echo "║ OpenHermit Phone Agent + Audit Logging ║" | ||
| echo "╚════════════════════════════════════════════════════════╝" | ||
| echo "" | ||
| veilpiercer log "AGENT_START" "Phone agent session started" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Propagate audit command failures.
If veilpiercer log fails, the agent continues without recording the event. If veilpiercer verify fails, the script still breaks and exits as though verification succeeded. This violates the audit contract used by run-with-audit.sh Lines 9-20 and work-agent.sh Lines 80-102. Check each result and terminate nonzero on failure.
Also applies to: 11-18, 24-24, 28-28
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@phone-agent.sh` at line 6, Update the audit command invocations in
phone-agent.sh, including the AGENT_START log and the additional veilpiercer
log/verify calls, to check each command’s exit status. Immediately terminate
with a nonzero status when any audit operation fails, ensuring the script cannot
continue or report successful verification after a failure.
| while true; do | ||
| read -p "You: " msg | ||
| if [ "$msg" = "exit" ]; then |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files:\n'
git ls-files | rg '(^|/)phone-agent\.sh$|\.sh$' || true
printf '\nphone-agent.sh outline/size:\n'
wc -l phone-agent.sh
ast-grep outline phone-agent.sh || true
printf '\nRelevant phone-agent.sh contents:\n'
cat -n phone-agent.sh | sed -n '1,140p'
printf '\nSearch for veilpiercer call sites and cleanup:\n'
rg -n "veilpiercer|AGENT_END|cleanup|log|verify|read -p|read -r" phone-agent.sh . || trueRepository: HCF-STUDIOS/openhermit
Length of output: 50379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Behavioral probe for Bash read with EOF in a while-true loop; no repo code is executed.
printf 'Bash read EOF behavior probe:\n'
{
i=0
while true; do
read -p "You: " msg
((i+=1))
if [ "$msg" = "exit" ]; then
printf 'exit branch at i=%s msg=%s\n' "$i" "$msg"
break
fi
printf 'loop iteration i=%s msg=%s\n' "$i" "$msg"
if [ "$i" -gt 8 ]; then
printf 'breaking after safe upper bound iterations; EOF appears to be handled by loop exit.\n'
break
fi
done
} < /dev/nullRepository: HCF-STUDIOS/openhermit
Length of output: 190
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Locate phone-agent.sh:\n'
git ls-files | grep -E '(^|/)phone-agent\.sh$' || true
printf '\nRelevant phone-agent.sh contents:\n'
if [ -f phone-agent.sh ]; then
wc -l phone-agent.sh
cat -n phone-agent.sh | sed -n '1,160p'
fi
printf '\nSearch only phone-agent.sh for read and lifecycle symbols:\n'
if [ -f phone-agent.sh ]; then
rg -n "read -p|read -r|read|AGENT_END|exit|cleanup|trap|veilpiercer|log|verify" phone-agent.sh || true
fiRepository: HCF-STUDIOS/openhermit
Length of output: 1893
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Minimal Bash read EOF semantics probe:\n'
tmp="$(mktemp -u)"
cat > "$tmp.sh" <<'BASH'
set -u
i=0
while true; do
read -p "You: " msg
((i+=1))
printf '%s|read_status=%s|msg="[%s]"|newline_after_prompt_seen=%s\n' "$i" "$?" "$msg" "$?" >&2
if [ "$msg" = "exit" ]; then
printf 'exit branch\n'
break
fi
if [ "$i" -ge 5 ]; then
printf 'break upper bound\n'
break
fi
done
BASH
printf 'With empty stdin:\n'
bash "$tmp.sh" < /dev/null
printf '\nUsing IFS= read -r status handling:\n'
bash "$tmp.sh" < "$tmp.sh" || true
rm -f "$tmp.sh" "$tmp" "$tmp"Repository: HCF-STUDIOS/openhermit
Length of output: 870
🏁 Script executed:
#!/bin/bash
set -euo pipefail
tmp="$(mktemp -u)"
cat > "$tmp" <<'BASH'
#!/bin/bash
set -u
i=0
while true; do
trap 'printf "caught signal\n"; exit 0' INT TERM
read -p "You: " msg
((i+=1))
printf '%s|read_status=%s|msg="[%s]"\n' "$i" "$?" "$msg" >&2
if [ "$msg" = "exit" ]; then
printf 'exit branch\n'
break
fi
if [ "$i" -ge 5 ]; then
printf 'break upper bound\n'
break
fi
done
BASH
printf 'Bash read with trailing escape newline then EOF:\n'
printf 'abc\\\n' | bash "$tmp"
printf '\nRead-only status probe from bash manual: "read returns false when end of file is reached"\n'
bash -n "$tmp" || true
rm -f "$tmp"Repository: HCF-STUDIOS/openhermit
Length of output: 446
Handle EOF before logging a closed stdin as a repeated message.
read returns false at EOF, but the loop ignores the status and treats the previous msg value as a new user message on each empty-line iteration, so abrupt stdin closure can repeatedly append USER_MSG events. Route EOF through the normal cleanup path and use IFS= read -r -p "You: " msg to parse the last user input exactly.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 9-9: read without -r will mangle backslashes.
(SC2162)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@phone-agent.sh` around lines 8 - 10, Update the input loop around the read
command to use IFS= read -r -p "You: " msg and check its return status before
processing msg. On EOF, route execution through the existing normal cleanup path
instead of logging or appending another USER_MSG event; preserve the current
exit-command handling for valid input.
Source: Linters/SAST tools
| while true; do | ||
| read -p "You: " msg | ||
| if [ "$msg" = "exit" ]; then | ||
| veilpiercer log "AGENT_END" "Session ended - $COUNT messages" | ||
| echo "" | ||
| echo "✓ Verifying audit trail..." | ||
| veilpiercer verify | ||
| break | ||
| fi |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Add interruption cleanup for audited sessions.
Ctrl-C, SIGTERM, and similar termination paths bypass AGENT_END and veilpiercer verify; only typing exit performs cleanup. Add an idempotent cleanup function registered with trap so interrupted sessions are closed and verification failures are propagated.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 9-9: read without -r will mangle backslashes.
(SC2162)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@phone-agent.sh` around lines 8 - 16, Update the interactive loop around
`AGENT_END` and `veilpiercer verify` by adding an idempotent cleanup function
and registering it with traps for Ctrl-C, SIGTERM, and related termination
signals. Ensure cleanup logs the session end, runs audit verification once, and
preserves or propagates verification failures across both typed `exit` and
interrupted termination paths.
| sanitized=$(echo "$msg" | sed 's/"//g' | cut -c1-100) | ||
| veilpiercer log "USER_MSG" "[$COUNT] $sanitized" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files around phone-agent/veilpiercer =="
git ls-files | rg '(^|/)phone-agent\.sh$|veilpiercer|\.veilpiercer|README|privacy|POLIC|SECURITY|config' || true
echo
echo "== phone-agent.sh =="
if [ -f phone-agent.sh ]; then
cat -n phone-agent.sh
fi
echo
echo "== search for USER_MSG / persisted ledger / redaction =="
rg -n "USER_MSG|\.veilpiercer|veilpiercer|redact|privacy|policy|PII|password|secret|token|credential|truncate|sanitize|sanitized" . --glob '!node_modules' --glob '!dist' --glob '!build' || trueRepository: HCF-STUDIOS/openhermit
Length of output: 50379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate phone-agent.sh =="
fd -a '^phone-agent\.sh$' . || true
echo
echo "== inspect phone-agent.sh =="
while IFS= read -r -d '' f; do
echo "--- $f"
cat -n "$f"
done < <(fd '^phone-agent\.sh$' . -print0)
echo
echo "== targeted USR_MSG and veilpiercer mentions =="
rg -n "USER_MSG|VEIL|veil|veilpiercer|phone|PHONE|\.veilpiercer\.jsonl" run-with-audit.sh start-hermit-audit.sh phone-agent.sh 2>/dev/null || trueRepository: HCF-STUDIOS/openhermit
Length of output: 536
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== phone-agent.sh =="
cat -n phone-agent.sh
echo
echo "== targeted mentions =="
rg -n "USER_MSG|VEIL|veil|veilpiercer|phone|PHONE|\.veilpiercer\.jsonl|redact|privacy|policy" run-with-audit.sh start-hermit-audit.sh phone-agent.sh README.md LICENSE* 2>/dev/null || true
echo
echo "== inspect audit log implementation snippets =="
rg -n "function .*veil|declare -f .*veil|veilpiercer|USER_MSG|\\.veilpiercer" . --glob '*.sh' --max-count 80 || trueRepository: HCF-STUDIOS/openhermit
Length of output: 4706
Do not persist raw phone messages without an explicit privacy policy.
Removing quotes and truncating to 100 characters does not redact sensitive content. USER_MSG writes user-controlled phone messages to the persisted .veilpiercer.jsonl audit ledger; use approved redaction or metadata/digests unless content retention, access controls, and retention limits are explicitly required and documented.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@phone-agent.sh` around lines 23 - 24, Update the USER_MSG logging in the
message-processing flow to avoid persisting raw phone-message content; replace
the sanitized message payload with the approved redaction, metadata, or digest
mechanism. Do not rely on quote removal or truncation as privacy protection, and
preserve the existing count/context information in veilpiercer log.
| veilpiercer log "WORK_AGENT_START" "Work tracking session started" | ||
|
|
||
| while true; do | ||
| read -p "Agent> " cmd |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)work-agent\.sh$' || true
for f in $(git ls-files | rg '(^|/)work-agent\.sh$' || true); do
echo "== outline/stat: $f =="
wc -l "$f"
echo "== read usages: $f =="
rg -n '^\s*read\b|read\s+-' "$f" || true
echo "== relevant lines: $f =="
sed -n '1,80p' "$f" | cat -n
done
echo "== bash read behavior probe =="
bash -c 'cmd="x\\\\y"; read -p "cmd? " c; printf "without -r: %q\n" "$c"'
bash -c 'cmd="x\\\\y"; IFS= read -r -p "cmd? " c; printf "with -r: %q\n" "$c"'
bash -c 'task="name\\\\value"; IFS= read -r -p "task? " t; printf %q "$t"; printf "\n"'Repository: HCF-STUDIOS/openhermit
Length of output: 3414
Preserve literal backslashes in interactive inputs.
read without -r treats \ as an escape character, so command and task-name inputs can be altered before being written to .current_task, work_tasks.csv, and veilpiercer logs. Use IFS= read -r -p ... for both inputs.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 14-14: read without -r will mangle backslashes.
(SC2162)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` at line 14, Update both interactive input reads in
work-agent.sh to use IFS= read -r -p, preserving literal backslashes in command
and task-name values before they are written to .current_task, work_tasks.csv,
and veilpiercer logs.
Source: Linters/SAST tools
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
if [ -f work-agent.sh ]; then
echo "## file exists"
wc -l work-agent.sh
echo "## outline/contents"
cat -n work-agent.sh | sed -n '1,220p'
echo "## read uses"
rg -n "read -p|if|exit|trap|while" work-agent.sh
else
echo "work-agent.sh not found"; git ls-files | rg 'work-agent\.sh|agent|work'
fiRepository: HCF-STUDIOS/openhermit
Length of output: 4546
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Behavioral probe for the relevant shell pattern in an isolated subshell.
python3 - <<'PY'
import subprocess, textwrap, shlex
cases = {
"normal_exit": 'while true; do read -p "Agent> " cmd; echo "CMD<$cmd>"; done',
"eof_with_stripped_read": 'while true; do read -p "Agent> " cmd || continue; echo " CMD<$cmd>"; done',
"eof_with_unstripped_read": 'while true; do read -p "Agent> " cmd; echo " CMD<$cmd>"; done',
}
for name, script in cases.items():
print(f"\n## {name}")
proc = subprocess.run(["bash", "-c", script], input=b"", stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
print("exit:", proc.returncode)
print("stdout:", proc.stdout.decode().splitlines()[:10])
print("stderr:", proc.stderr.decode().splitlines()[:10])
script = r'''
set -e
while true; do
read -p "Agent> " cmd
echo "CMD<$cmd>"
done
'''
print("\n## set -e + eof")
proc = subprocess.run(["bash", "-c", script], input=b"", stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
print("exit:", proc.returncode)
print("stdout:", proc.stdout.decode().splitlines()[:10])
print("stderr:", proc.stderr.decode().splitlines()[:10])
PYRepository: HCF-STUDIOS/openhermit
Length of output: 1014
Handle EOF from read -p "Agent> " cmd.
At line 14, read exits the script on Ctrl-D/closed input but the set -eu script does not reach WORK_AGENT_END, final verification, or any cleanup. Detect the failed read and route through the normal session-finalization before exiting.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 14-14: read without -r will mangle backslashes.
(SC2162)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` at line 14, Update the command-reading loop around read in the
work-agent script to detect EOF or another failed read, then route through the
existing WORK_AGENT_END/session-finalization path so verification and cleanup
still run before exiting. Preserve normal command handling for successful reads
and ensure the EOF path terminates with the appropriate exit status after
finalization.
| help) | ||
| echo "" | ||
| echo "Commands:" | ||
| echo " time <task> - Start timing a task" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Make the documented time <task> command work.
The help text advertises time <task>, but the case only accepts exactly time; time Design review is rejected as unknown. Either parse the argument or document time followed by the prompt.
Also applies to: 29-30
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` at line 20, Update the command dispatch case for time so it
accepts the documented task argument, including prompts with spaces, and passes
that task to the timing workflow. Keep the help text and existing behavior for
other commands unchanged.
| time) | ||
| read -p "Task name: " task | ||
| START=$(date +%s) | ||
| echo "$task" > .current_task | ||
| echo "$START" > .task_start_time | ||
| veilpiercer log "TASK_STARTED" "$task" | ||
| echo "✓ Timing: $task" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Do not overwrite an active timer.
A second time command replaces .current_task and .task_start_time, losing the first task without a completion event or billable record. Refuse to start until the current task is stopped.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 30-30: read without -r will mangle backslashes.
(SC2162)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` around lines 29 - 35, Update the time command handling to
check for an existing active timer before writing .current_task or
.task_start_time. If a timer is active, refuse to start the new task and leave
the existing timer state unchanged; otherwise preserve the current task
initialization, TASK_STARTED logging, and timing output.
| echo "$task" > .current_task | ||
| echo "$START" > .task_start_time |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files matching work-agent =="
fd -a 'work-agent' . || true
echo "== target file excerpt =="
if [ -f work-agent.sh ]; then
nl -ba work-agent.sh | sed -n '1,120p'
fi
echo "== symlink candidates and current directory behavior =="
python3 - <<'PY'
import os
for p in ('.current_task','.task_start_time','.task_start_time.'):
print(f"{p}: exists={os.path.lexists(p)} islink={os.path.islink(p)} abs={os.path.abspath(p)}")
PYRepository: HCF-STUDIOS/openhermit
Length of output: 296
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target file excerpt =="
awk '{printf "%7d\t%s\n", NR, $0}' work-agent.sh | sed -n '1,140p'
echo "== file metadata =="
stat -c '%a %n' work-agent.sh 2>/dev/null || ls -l work-agent.sh
echo "== symlinks and current directory writes for target paths =="
python3 - <<'PY'
import os
for p in ('.current_task','.task_start_time','.task_start_time.'):
try:
print(f"{p}: exists={os.path.lexists(p)} islink={os.path.islink(p)} abs={os.path.abspath(p)} inode={os.lstat(p).st_ino if os.path.lexists(p) else None}")
except FileNotFoundError:
print(f"{p}: exists=False")
PY
echo "== references to state files in repository =="
grep -RIn '\.current_task\|\.task_start_time' . --exclude-dir=.git 2>/dev/null || trueRepository: HCF-STUDIOS/openhermit
Length of output: 6814
Use a private state directory for work-agent temporary files.
The script writes state-adjacent paths are predictable relative paths, and work_tasks.csvis appended at line 49. If the user runs the script as an executable from an untrusted checkout, these relative writes can overwrite or append to attacker-controlled files. Put the state in a private, permission-restricted directory and derivework_tasks.csv` from an installed canonical location instead of relying on the caller’s CWD.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` around lines 32 - 33, Update work-agent.sh to create and use a
private, permission-restricted state directory for temporary files such as
.current_task and .task_start_time, rather than writing predictable paths in the
caller’s working directory. Also change the work_tasks.csv append logic to
resolve the file from the script’s installed canonical location instead of the
current working directory.
| DURATION=$((END - START)) | ||
| MINS=$((DURATION / 60)) | ||
|
|
||
| echo "$TASK,$MINS,$(date)" >> work_tasks.csv |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Do not parse raw task names as CSV fields.
A task named Client A, 9999 makes awk treat 9999 as its duration, corrupting the invoice total. Use an unambiguous internal format (for example, TSV with validation) or a CSV-aware serializer/parser.
Also applies to: 72-72
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@work-agent.sh` at line 49, Update the task persistence and parsing around the
work_tasks.csv append and the awk processing near line 72 so task names
containing commas cannot shift the duration field. Use a CSV-aware
serializer/parser or replace the internal format with a validated unambiguous
delimiter, and ensure invoice totals continue reading the actual MINS value.
Description
Fixes issue #248 regarding reasoning tag handling in agent responses.
Changes
Testing
Summary by CodeRabbit