Issue description
Writes to a CARE artifact workspace are screened against a deny-list that matches the filename only - the rules are path globs, and the ruleset performs no inspection of what the file contains. In stage 3.2 this blocks legitimate guardrail policy documents. The SME does not choose these filenames - the interviewer agent generates them, and it is instructed to make each name describe the rule the file holds. So an SME-approved rule about credential handling produces a filename containing "credentials" or "secret", and the write is refused.
The CARE interviewer's file-writing capability is constructed with PERMISSIVE_RULESET from pydantic_ai_backends (services/care/agent_factory.py:99). That ruleset denies writes to any path matching a fixed list of globs:
**/.env **/.env.* **/*.pem **/*.key **/*.crt
**/credentials* **/secrets* **/*secret* **/*password*
**/.aws/** **/.ssh/** **/.gnupg/**
During stage 3.2 the interviewer tried to record an SME-approved secrets-handling rule, and the write was refused:
The SME supplied an alternative filename. Refused again:
guardrails/credentials_and_secrets.md matches **/credentials*
guardrails/secret_handling_policy.md matches **/*secret*
Neither file contained a secret. Both were policy documents stating that credentials must never be written to a log, a workspace record or an artifact - the rule the SME had just approved.
Neither the agent nor the SME had any way to arrive at a permitted name. The first filename was chosen by the interviewer agent, not the SME - and the agent was following its instructions: the interviewer prompt states "Filename conveys category; don't repeat it in frontmatter" (services/care/agent_prompts.py:340), so a rule about credential handling gets a filename about credential handling. That same prompt documents two reserved paths (consolidation/log.md and _archive/) but says nothing about a secrets deny-list, and the stage 3.2 prompt doesn't mention filename constraints at all. The refusal names neither the matched pattern nor a permitted alternative, so the SME's replacement name was a guess - and it failed the same way on a different pattern.
Impact. The rule was recorded only by abandoning the dedicated file and appending it to guardrails/forbidden_actions.md.
Steps to reproduce the behavior
- Start a CARE interview and proceed to stage 3.2 (Policy & Guardrails).
- Ask the interviewer to record a rule about credential or token handling - e.g. "credentials must never be written to a log, a workspace record, or any artifact."
- The interviewer names the artifact after the rule's subject, as its prompt instructs - in this run,
guardrails/credentials_and_secrets.md. The write is refused with "Protect sensitive and system files".
- The refusal doesn't say which word caused it, so a good-faith rename that still describes the rule — here
guardrails/secret_handling_policy.md - matches a different pattern in the same list and is refused again.
- Continue the stage by putting instructions in another file say,
forbidden_actions.md. It completes normally; guardrails/ contains no secret-handling file, and nothing flags its absence.
Expected Behavior
A guardrail policy document should be writable under the name that describes it. Credential and token handling is a subject stage 3.2 actively probes for, and the interviewer is instructed to name each file after its subject - so these filenames are generated on any run where an SME approves a rule in this area. Filenames are not something the SME picks, or necessarily even sees.
Failing that, two smaller improvements would each have been enough to recover unaided:
- The refusal names the matched pattern and suggests a permitted filename, instead of a generic "Protect sensitive and system files".
- The stage does not report complete when an approved rule was relocated after a refused write - or at minimum, the relocation is visible in the artifact tree afterwards.
Relevant log output
Permission denied for write on 'guardrails/credentials_and_secrets.md': Protect sensitive and system files
Permission denied for write on 'guardrails/secret_handling_policy.md': Protect sensitive and system files
Source of the message and patterns:
pydantic_ai_backends/permissions/presets.py -> PERMISSIVE_RULESET (write/edit rules)
services/care/agent_factory.py:99 -> ConsoleCapability(permissions=PERMISSIVE_RULESET)
Questions
- Is the
pydantic_ai_backends deny-list intended to apply to CARE artifact writes, or is it inherited from the library default?
- If intended, could the refusal name the matched pattern and suggest a permitted filename?
Issue description
Writes to a CARE artifact workspace are screened against a deny-list that matches the filename only - the rules are path globs, and the ruleset performs no inspection of what the file contains. In stage 3.2 this blocks legitimate guardrail policy documents. The SME does not choose these filenames - the interviewer agent generates them, and it is instructed to make each name describe the rule the file holds. So an SME-approved rule about credential handling produces a filename containing "credentials" or "secret", and the write is refused.
The CARE interviewer's file-writing capability is constructed with
PERMISSIVE_RULESETfrompydantic_ai_backends(services/care/agent_factory.py:99). That ruleset denies writes to any path matching a fixed list of globs:During stage 3.2 the interviewer tried to record an SME-approved secrets-handling rule, and the write was refused:
The SME supplied an alternative filename. Refused again:
guardrails/credentials_and_secrets.mdmatches**/credentials*guardrails/secret_handling_policy.mdmatches**/*secret*Neither file contained a secret. Both were policy documents stating that credentials must never be written to a log, a workspace record or an artifact - the rule the SME had just approved.
Neither the agent nor the SME had any way to arrive at a permitted name. The first filename was chosen by the interviewer agent, not the SME - and the agent was following its instructions: the interviewer prompt states "Filename conveys category; don't repeat it in frontmatter" (
services/care/agent_prompts.py:340), so a rule about credential handling gets a filename about credential handling. That same prompt documents two reserved paths (consolidation/log.mdand_archive/) but says nothing about a secrets deny-list, and the stage 3.2 prompt doesn't mention filename constraints at all. The refusal names neither the matched pattern nor a permitted alternative, so the SME's replacement name was a guess - and it failed the same way on a different pattern.Impact. The rule was recorded only by abandoning the dedicated file and appending it to
guardrails/forbidden_actions.md.Steps to reproduce the behavior
guardrails/credentials_and_secrets.md. The write is refused with "Protect sensitive and system files".guardrails/secret_handling_policy.md- matches a different pattern in the same list and is refused again.forbidden_actions.md. It completes normally;guardrails/contains no secret-handling file, and nothing flags its absence.Expected Behavior
A guardrail policy document should be writable under the name that describes it. Credential and token handling is a subject stage 3.2 actively probes for, and the interviewer is instructed to name each file after its subject - so these filenames are generated on any run where an SME approves a rule in this area. Filenames are not something the SME picks, or necessarily even sees.
Failing that, two smaller improvements would each have been enough to recover unaided:
Relevant log output
Questions
pydantic_ai_backendsdeny-list intended to apply to CARE artifact writes, or is it inherited from the library default?