Skip to content

Commit bab2223

Browse files
committed
Add outcome-sensitive Bash cwd analysis
1 parent af3a543 commit bab2223

31 files changed

Lines changed: 2133 additions & 62 deletions

IMPLEMENTATION_PLAN.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ priorities.
293293
decoded-wrapper state, and dynamic fail-closed compatibility attribution
294294
whenever cwd joins to Unknown. Keep OpenSpec task 6.5 open, then add the
295295
remaining loop cases and Netclaw approval matrix after implementation.
296+
The non-loop state engine is now implemented for lists, pipelines,
297+
substitutions, subshells, and decoded wrappers; loop iteration state and
298+
removal of the temporary mutation rejection remain next.
296299
- [ ] Complete PowerShell `$()` discovery in `foreach` expressions and add the
297300
Netclaw approval-matrix cases. The simple-command slice is delivered for
298301
ordinary, adjacent, quoted, here-string, redirect, standalone,

openspec/changes/v0-3-structured-shell-analysis/specs/bounded-shell-analysis/spec.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,14 @@ unless all executable regions and transfers are discovered.
297297
- **THEN** the `pwd` cwd is unknown because `cd` may fail and `;` still continues
298298
- **THEN** the analyzer does not publish `/maybe` as the sole cwd
299299

300+
#### Scenario: Bash cd environment and physical resolution stay explicit
301+
- **WHEN** Bash parses a bare relative `cd sub` without proved `CDPATH` and `cdable_vars` state
302+
- **THEN** the successful cwd is unknown rather than a lexical `<cwd>/sub` guess
303+
- **WHEN** Bash parses `cd ./sub` or `cd ../sub` with an exact incoming cwd
304+
- **THEN** the successful cwd may remain exact because those operands bypass directory search
305+
- **WHEN** Bash parses `cd -P`, `cd -@`, `pushd`, or `popd` without the required filesystem or directory-stack facts
306+
- **THEN** the successful cwd is unknown
307+
300308
#### Scenario: Zero-iteration loop path
301309
- **WHEN** a loop may execute zero times and its body changes cwd
302310
- **THEN** the post-loop state includes the pre-loop possibility

openspec/changes/v0-3-structured-shell-analysis/specs/consumer-compatibility/spec.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ signal.
4747
- **THEN** the clause contains a synthetic `<dynamic-cwd>` `DynamicSkip` attribution argument with `Resolved=null`
4848
- **THEN** no synthetic cwd-attribution argument selects one possible exact path
4949

50+
#### Scenario: Cwd rebasing preserves resolver-owned operand semantics
51+
- **WHEN** an executable-specific rule transforms an authored path operand such as curl `@../request.json`
52+
- **THEN** outcome-sensitive cwd rebasing uses the retained logical resolver operand rather than reconstructing it from `Arg.Raw` or `ClauseElement.Value`
53+
- **THEN** split and equals-form options update their exact corresponding Arg and ClauseElement coordinates
54+
- **THEN** decoded wrappers retain the same resolver provenance while inheriting their invocation cwd
55+
56+
#### Scenario: Exact outcome partition recovers a cwd-blocked path
57+
- **WHEN** parse-order attribution initially makes a relative argument or redirect dynamic, but outcome analysis later proves its execution cwd exact
58+
- **THEN** retained path-slot provenance permits an exact compatibility path without rescanning decoded text
59+
- **THEN** a sibling partition whose cwd remains unknown keeps the operand dynamic
60+
61+
#### Scenario: Dynamic redirect preserves authored target spelling
62+
- **WHEN** a quoted relative redirect target becomes dynamic after cwd outcomes join
63+
- **THEN** its compatibility `Redirect.Target` retains the target-only authored spelling including quotes
64+
- **THEN** the redirect is marked `IsDynamicSkip=true` and its ClauseElement exact resolution is cleared
65+
5066
### Requirement: Unparseable results are never authorization evidence
5167
When `ParsedCommand.IsUnparseable=true`, `Commands` and `Clauses` SHALL be
5268
empty. `Syntax` MAY contain partial diagnostic evidence, and the consumer guide

openspec/changes/v0-3-structured-shell-analysis/tasks.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@
7777
conservative `lastpipe` / `pipefail`, ordered iteration plans,
7878
decoded-wrapper inheritance, and dynamic fail-closed compatibility
7979
sanitization before implementing the state pass.
80+
- [x] 6.5b Apply outcome-sensitive cwd analysis to existing Bash lists,
81+
pipelines, substitutions, subshells, and decoded wrappers; rebase exact
82+
compatibility paths and retain `<dynamic-cwd>` after conservative joins.
83+
- [ ] 6.5c Carry ordered loop binding and cwd state through zero-or-more
84+
iterations, then remove the temporary loop-mutation rejection.
8085
- The first static-value slice deliberately leaves occurrence cwd Unknown
8186
and rejects loop shell-state mutation, nested active-binding reuse, or
8287
loops reached after recognized prior shell-state mutation. A separate

0 commit comments

Comments
 (0)