REQ-F-061: Symlink Loop Detection in Traversal Utilities
Tier: Framework-Automatic | Priority: P1
Source: §66 Symlink Loop and Recursive Traversal Exhaustion
Addresses: Severity: High / Token Spend: Medium / Time: Critical / Context: Low
Description
The framework's filesystem traversal utilities (used by commands that copy, delete, archive, or search recursively) MUST track visited directory inodes and exit with a structured error immediately upon detecting a revisited inode (circular symlink). The framework MUST additionally enforce a maximum traversal depth (default: 50, configurable via --max-depth). Both checks MUST apply to the framework's built-in traversal API; commands using the framework's API get this protection automatically.
Acceptance Criteria
- A recursive delete on a directory containing a circular symlink exits with code 4 and
error.code: "SYMLINK_LOOP"before exhausting memory - The error includes
path(where the loop was detected) andloop_target(the directory it points back to) --max-depth 10limits traversal to 10 directory levels- A directory without circular symlinks traverses normally to full depth
Schema
Type: response-envelope.md
The framework emits a PRECONDITION (4) error response with error.code: "SYMLINK_LOOP" and structured fields for the detected loop.
Wire Format
{
"ok": false,
"data": null,
"error": {
"code": "SYMLINK_LOOP",
"message": "Circular symlink detected during traversal",
"retryable": false,
"phase": "execution",
"path": "/project/a/b/link",
"loop_target": "/project/a",
"completed_count": 142
},
"warnings": [],
"meta": { "duration_ms": 80 }
}
Example
Framework-Automatic: no command author action needed. Commands using the framework's traversal API get loop detection automatically.
# Directory tree contains a → b → c → a symlink loop
$ mytool archive /project --json
{
"ok": false,
"data": null,
"error": {
"code": "SYMLINK_LOOP",
"message": "Circular symlink detected during traversal",
"retryable": false,
"phase": "execution",
"path": "/project/c/link_back",
"loop_target": "/project/a",
"completed_count": 142
},
...
}
→ exits 4 before exhausting memory; agent knows where the loop is
Related
| Requirement | Tier | Relationship |
|---|---|---|
| REQ-F-004 | F | Provides: ResponseEnvelope shape for the SYMLINK_LOOP error |
| REQ-F-001 | F | Provides: PRECONDITION (4) exit code used for symlink loop errors |
| REQ-F-040 | F | Composes: path and loop_target fields in the error are always absolute paths |
| REQ-F-011 | F | Composes: max-depth and timeout together bound traversal resource use |