Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…, lazy env-snapshot errors Address review feedback by: - Rewriting the Decision Summary cleanup bullet to match the detailed rules (symlink replacements are unlinked; only identity-matched directories are recursively removed). - Adding "child launch / spawn failure after tmpdir creation" as an explicit terminal outcome so the tmpdir guarantee covers cases like a discovered script being removed between discovery and spawn or an OS rejection of a RunOptions.env entry. - Clarifying that the shell env-var prefix on the CLI reuses the inherited-env tier and does not introduce a new override-precedence level above -e or global env. - Preserving SPEC §9.1's sync-never-throws guarantee when RunOptions.env is an exotic object (Proxy, throwing getter) by routing snapshot exceptions through the pre-iteration error path. - Spelling out the five-tier env precedence list in the §8 SPEC-update mapping and extending §7.2 to cover spawn-path failures. Status remains Proposed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expands ADR-0004 with two new decisions that make scripts easier to write: - §3 Project-root cwd. Scripts run with LOOPX_PROJECT_ROOT as their child-process cwd instead of the workflow directory, superseding SPEC §6.1's current "workflow directory as cwd" rule. Eliminates the \$ROOT="\$LOOPX_PROJECT_ROOT" prefix boilerplate currently repeated in every workflow script. - §4 LOOPX_WORKFLOW_DIR injection. Absolute path to the currently-spawned script's workflow directory, refreshing per-spawn alongside LOOPX_WORKFLOW. Correct across intra-workflow goto, cross-workflow goto (destination sees its own dir, not caller's), deep chains, and loop reset. Gives scripts a one-token reference to workflow-local assets without dirname/import.meta.url tricks. Also corrects SPEC §3.3's stale claim that closer-node_modules/loopx precedence is "a natural consequence of running scripts with the workflow directory as cwd" — module resolution is file-relative, not cwd-relative. Renamed from 0004-tmpdir-and-env.md → 0004-script-execution-context.md to reflect the broader scope (now four decisions: LOOPX_TMPDIR, RunOptions.env, project-root cwd, LOOPX_WORKFLOW_DIR). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rget Apply review feedback: weaken the async-generator cleanup claim (no GC-based guarantee), make the absolute discovery-time invocation path a normative rule so $0 / import.meta.url equal LOOPX_WORKFLOW_DIR, list §5.1 in Affected SPEC Sections so its "non-zero exit" reference aligns with §7.2's new spawn-failure category, note that LOOPX_PROJECT_ROOT is symlink-preserving like LOOPX_WORKFLOW_DIR, drop src/env.ts and src/execution.ts implementation refs, and correct the "loopx env set" consequence to reflect its persistent-global role. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y path spelling and warning cardinality Address review feedback pre-acceptance: - JS/TS dirname(fileURLToPath(import.meta.url)) equality with LOOPX_WORKFLOW_DIR is now non-normative under symlinks (Node canonicalizes the main module's URL by default; Bun's behavior is unspecified). Bash $(dirname \"\$0\") equality remains normative. LOOPX_WORKFLOW_DIR is authoritative for JS/TS code. - Replace \"path-spelling preserved\" prose with \"no extra canonicalization by loopx\" for LOOPX_PROJECT_ROOT, explicitly acknowledging that process.cwd() may canonicalize while RunOptions.cwd is used verbatim. - Normalize cleanup warning cardinality to one stderr warning per distinct anomaly, no aggregation or dedup; test-friendly. - Retarget \"§3.2 / §7.1 pre-iteration\" to §7.1 only; add §6.2 and §6.3 entries for the language-specific invocation-path consequences. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ats to entry scripts Closes the logical gap between "LOOPX_PROJECT_ROOT is absolute" and the prior "RunOptions.cwd used verbatim" wording: a relative cwd is now resolved via path.resolve(process.cwd(), options.cwd) at call time with no further realpath. Broadens the JS/TS import.meta.url equality and §3.3 module-resolution caveats to cover symlinked entry script files (not only symlinked workflow directories), matching SPEC §5.1's symlink policy on both. Adds a one-line note that OS-rejected RunOptions.env entries don't surface under maxIterations: 0 since no spawn occurs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mlink scope, tighten warning cardinality - Context: fix confused `.loopx/shared/` sentence (workflow-local paths break after cross-workflow goto because $LOOPX_WORKFLOW updates). - §2 RunOptions.env: add "inherited process.env snapshotted once per run" rule so deterministic env is a per-run property, not just a RunOptions.env property. - §1 warning cardinality: replace "any other distinct cleanup error surface" catch-all with a closed enumeration of three categories (leave-in-place, top-level recursive-removal failure, partial-dir cleanup failure on creation error). - §3 / §4 / Affected-SPEC / Tests: consistently frame JS/TS import.meta.url non-guarantee around any symlink in the absolute discovery-time entry path (workflow dir, entry script file, or intermediate component) rather than only the first two. Frame the loopx guarantee around what loopx controls (absolute invocation path + LOOPX_WORKFLOW_DIR). - Consequences: fix incorrect claim that `-e`/`loopx env set` reach "above env files" (`-e` is local env file tier; `loopx env set` writes the global env file tier). Replace RunOptions.env rationale: it exists as an in-memory per-call override layer that (a) avoids mutating process.env, (b) avoids writing a temp env file, and (c) layers on top of RunOptions.envFile — not because programmatic callers lack an -e equivalent (they have RunOptions.envFile). - Tests: add inherited-env snapshot test, intermediate-symlink scenario test, and updated warning-cardinality assertions to match the closed enumeration. Status remains Proposed.
…eanup Addresses review feedback on ADR-0004: - Distinguish effective-cwd (loopx-controlled) from cwd string spelling (runtime-reported); runtime APIs may canonicalize while LOOPX_PROJECT_ROOT preserves caller spelling. - Document that PWD is not a protocol variable; loopx neither sets nor unsets it, Bash regenerates $PWD on startup. - Specify partial tmpdir cleanup when identity capture fails: single non-recursive rmdir attempt, then leave-in-place + category-3 warning. - Make RunOptions.env shape validation explicit under maxIterations: 0. - Extend Affected SPEC Sections list with §5.1 symlink-path preservation and §12 tmpdir/spawn exit-code coverage; note envFile resolution under the new cwd semantics. - Soften "module resolution is unaffected by cwd" to apply specifically to script module resolution, not cwd-dependent tooling. - Scope byte-for-byte cwd test assertions to symlink-free fixtures; add filesystem-identity assertions for symlinked regimes. - Add Rejected / Deferred Alternatives section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix symbol-key contradiction in RunOptions.env shape validation (symbol-keyed entries are ignored, not invalid). Replace path.resolve with fs.realpath in the symlink-identity test convention (path.resolve is string-only and does not prove filesystem identity). Simplify warning cardinality to reflect that cleanup dispatches on a single top-level LOOPX_TMPDIR path, so each of the three categories fires at most once per cleanup and the three are mutually exclusive. Document the deliberate lazy-vs-call-time asymmetry between inherited process.env (lazy) and RunOptions.env / RunOptions.cwd (call-time), with a corresponding test recommendation. Clarify that RunOptions.envFile shares the local-env-file precedence tier with -e, and that invalid RunOptions.env shape / snapshot exceptions are pre-spawn failures that do not create a tmpdir. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes four internal inconsistencies flagged during review of ADR-0004: - Warning cardinality: categorize by cleanup routine (full safety vs. non-recursive rmdir), not by terminal-vs-creation outcome. Identity- captured creation-failure cleanup now correctly emits cat 1/2 rather than claiming mutually-exclusive-with-cat-3 while sharing a routine. - Closed-set language: switch to strict version — implementations emit no cleanup warnings outside the three categories; tests may assert their absence. - CLI symlink spelling: drop claim that CLI invocation through a symlink can preserve shell-side spelling. LOOPX_PROJECT_ROOT (CLI) is exactly process.cwd() at invocation; loopx does not consult \$PWD. Symlinked- project-root asymmetry reachable only via programmatic RunOptions.cwd. - Custom resolve hook: explicitly require the Node/tsx hook to preserve standard module resolution precedence via defaultResolve delegation, so workflow-local node_modules/loopx still wins after the cwd change. Also clarifies RunOptions.env inspection timing (synchronous at call time, errors deferred to pre-iteration) and notes that cleanup safety does not detect mount points inside \$LOOPX_TMPDIR. Status remains Proposed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s from review Fix contradictions and close gaps flagged in ADR-0001 review feedback: - Correct the relative-cwd symlink claim: symlinked components in a relative RunOptions.cwd are preserved by path.resolve(), so a symlink-preserving LOOPX_PROJECT_ROOT is not restricted to symlinked absolute cwd inputs. - Broaden cleanup warning category 2 from "Top-level recursive-removal failure" to "Top-level cleanup failure" covering lstat dispatch failure, top-level symlink unlink failure, and identity-matched recursive removal failure; preserves the at-most-one-warning model. - Make abort precedence across pre-iteration explicit: an already- aborted signal wins over validation, discovery, env loading, target resolution, version check, and tmpdir creation errors. - Document .loopx itself as a symlink: treated as an intermediate component of the absolute entry path with its spelling preserved. - Capture options.env getter exceptions through the lazy pre-iteration error path, like snapshot exceptions. - Tighten module-resolution hook language: any standard file-relative resolution wins over the CLI fallback, not only workflow-local. - Add SPEC §9.3 to Affected Sections; extend §7.2 bullet to cover tmpdir creation failure alongside other runtime error paths. - Add test recommendations for cleanup-internal failures, relative cwd with symlinked components, and symlinked .loopx directory entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… timing
Blocking fix: revise RunOptions.env malformed-name behavior. Node's
child_process does not reliably reject names containing "=" (a key like
"A=B" with value "C" may reach the child as A=B=C rather than a spawn
failure). Reframe runtime-level rejection around embedded NUL bytes as
the reliable case, note that other malformed-but-runtime-accepted names
have runtime-dependent child-observed behavior, and update the matching
test recommendation.
Also clarify: run() yields any final Output before the generator
settles, with cleanup guaranteed before { done: true } / abort
surfacing; abort precedence applies only once options.signal is
captured (a throwing signal getter is an ordinary snapshot error);
summary lists consumer-driven generator cancellation as a terminal
outcome; SPEC §3.3 update language uses "any standard file-relative
resolution of loopx wins over the CLI fallback" instead of the
workflow-local-implying "closer node_modules" phrasing; "OS rejection"
normalized to "runtime rejection" for consistency.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dering, and cleanup caveats Incorporate review feedback into ADR-0004 ahead of acceptance: - Warning cardinality: each cleanup warning must contain exactly one of three bracketed category tokens ([leave-in-place-refusal], [top-level-cleanup-failure], [partial-directory-cleanup-failure]) so tests can assert category identity without matching implementation- defined prose. - Options snapshot ordering: options.signal is read before options.env / cwd / envFile / maxIterations, making the existing "abort wins over options-snapshot exceptions" rule reachable when combined with a throwing env getter. Each option field is read at most once per call. - Non-abort pre-iteration error priority is implementation-defined except where already specified (e.g., invalid env shape + missing .loopx/ may surface either error). - Identity-capture-failure regime: document that the single rmdir is best-effort and may remove an unrelated empty directory if a same-user process swaps the mkdtemp directory before cleanup; this remains outside the race-resistant guarantee, as a deliberate trade-off against leaking the partial directory on the common identity-capture- failure path. - Promote the run() final-yield cleanup caveat into the Decision Summary LOOPX_TMPDIR bullet: cleanup on normal completion is guaranteed only once the async generator is driven to settlement; the final yielded Output is not itself settlement. - Soften device/inode wording in normative text to behavioral identity language, retaining device/inode as one POSIX implementation strategy. Update Affected SPEC Sections and Test Recommendations to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…, pre-iteration error scoping, and CLI grammar - Extend AbortSignal precedence to cover target argument validation (non-string `target`) and target syntax validation (empty, bare colon, etc.) — both previously left ambiguous. - Add CLI signal precedence paragraph: SIGINT/SIGTERM during the CLI pre-iteration phase mirrors programmatic `AbortSignal` precedence. - Scope the implementation-defined non-abort pre-iteration priority rule to the programmatic API only; CLI retains SPEC §7.1's concrete ordering. - Narrow "each option field read at most once" to permit normal one-pass enumeration of `options.env` proxies (single `ownKeys` plus per-property traps as required by the JS enumeration algorithm); additional enumeration passes and getter retries remain forbidden. - Add explicit pre-first-`next()` consumer-cancellation carve-out: `.return()` / `.throw()` on a generator that has not yet had `next()` invoked settles per standard async-generator semantics without observing signal state, even when the captured signal is already aborted. `runPromise()` has no equivalent carve-out. - Clarify call-time option snapshot vs lazy pre-iteration sequence so the "`RunOptions.env` shape validation" placement is unambiguous. - Pin "no CLI named-argument syntax" as an explicit §4.1/§4.2 affected SPEC bullet so the decision is traceable from this ADR. - Make the cleanup-warning category-token taxonomy and at-most-one-warning-per-attempt cardinality an explicit stable public testing contract. - Update §7.3, §9.1/§9.2, and §9.3 affected-SPEC bullets to reflect the new carve-outs; add test recommendations covering them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ield, run -h, warning scoping, and invalid options Addresses acceptance-level blockers raised in review: - Pre-first-next() consumer cancellation now explicitly wins over all captured call-time option snapshot errors (throwing option-field getters, invalid env shapes, invalid options values, invalid options.signal values), not only already-aborted signals. - Abort after the final yielded Output is explicitly spelled out as Option A — abort still wins until generator settlement; the final yield does not commit normal completion. - The "no CLI named-argument syntax" rule now explicitly preserves the existing SPEC §4.2 `run -h` / `--help` short-circuit, both in the decision summary and in the §4.1 / §4.2 affected-SPEC entry. - Cleanup-warning token requirement is scoped narrowly to LOOPX_TMPDIR cleanup warnings; other loopx warnings (version-check, unreadable package.json, invalid-entry, invalid env-file line, etc.) are outside the taxonomy and must not carry these tokens. - Invalid `options` (null, number, string, array, etc.) and invalid `options.signal` (non-AbortSignal-compatible values) are now defined: both are captured at call time and surfaced via the standard pre-iteration error path; a non-compatible signal does not enter the abort-precedence pathway. Also adds a timing-model terminology note at the start of §2 (call-time capture / pre-iteration surfacing / spawn-time runtime rejection) and corresponding test recommendations. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ith SPEC, broaden env-tier rejection, clarify LOOPX_DELEGATED and hard-link semantics Review feedback blockers and clarifications: - Bash `$PWD` / bare `pwd` are no longer claimed to equal `LOOPX_PROJECT_ROOT` byte-for-byte in any regime. Per POSIX, Bash retains an inherited `PWD` that names the current directory through symlinks, so a symlinked-logical ancestor shell can leave the child with a `$PWD` that differs from even a canonical `LOOPX_PROJECT_ROOT`. Tests must use `pwd -P` / `/bin/pwd` or filesystem identity, not `$PWD` / bare `pwd`. - "version-check error" removed from pre-iteration error-priority lists in §1 abort precedence, CLI signal precedence, non-abort priority, and the §7.3 / §9.3 affected-SPEC sections and matching test recommendation. SPEC §3.2 defines version-check outcomes as non-fatal warnings, so version checking is not a competing terminal-outcome mode; the ADR now says so explicitly. - Spawn-time runtime rejection language broadened from "a `RunOptions.env` entry" to "any child environment entry from any env tier (inherited, env file, `RunOptions.env`)" in §1 Cleanup, §1 Timing-model phase 3, affected §7.2, §9.3, §12, and the matching test recommendation. - `LOOPX_DELEGATED` explicitly documented as remaining an internal delegation guard outside this ADR's script-protocol-variable tier; `RunOptions.env` and env files may supply it to children without a loopx-side per-spawn override. - Hard-link refusal clarified: case 3 applies to top-level path replacement only; recursive cleanup under case 4 may unlink hard-link entries inside the identity-matched tmpdir, as ordinary recursive deletion would. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ping, recursive-removal test, version-check-under-n0 example, and make cwd/envFile validation explicit - Abort precedence: open paragraph now leads with the "usable signal captured" qualifier; removes the contradictory listing of invalid options / invalid options.signal as items abort can displace (these cases capture no signal and are surfaced as ordinary options-snapshot errors). Ripple fix to the §9.3 Affected SPEC bullet. - Cleanup-token scoping: tests may now assert that known non-cleanup warnings lack the three bracketed tokens (previously forbidden by the "or lack" clause, which contradicted the normative scoping rule). - Recursive-removal failure test: split the three category-2 sub-cases so only the lstat-failure and symlink-unlink-failure cases claim "path left in place"; the recursive-removal-failure sub-case no longer promises an intact tmpdir, since partial deletion may have occurred. - Token-scoping "no-token run" example: replaced version-mismatch-under-maxIterations:0 (never emits, since SPEC §3.2 / §7.1 / §4.2 skip version checking under -n 0) with env-file invalid-line per SPEC §8.1. - Explicit validation for options.cwd / options.envFile / options.maxIterations values: new subsection defines the string-only requirement for cwd/envFile, captures non-string values at call time, and surfaces via the standard pre-iteration error path. Propagated to the pre-first-next() carve-out list, the non-abort priority enumeration, §9.1/§9.2, §9.3, §9.5 Affected SPEC bullets, and a new test recommendation. Status remains Proposed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ummary, and LOOPX_DELEGATED role distinction Addresses acceptance-blocker review feedback: scope the public-contract surface explicitly, separate startup-reserved from script-protocol-protected for LOOPX_DELEGATED, tighten runPromise inherited-env timing as implementation-defined, and make name=value target-validation plus CLI signal precedence for target syntax explicit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… -- grammar, §3.2, and cleanup-token escaping Incorporate reviewer's acceptance-blocker feedback without marking the ADR Accepted: - runPromise() inherited-env snapshot timing: make implementation-defined relative to return (may capture at sync setup OR async continuation), resolving the prior contradiction between "asynchronously after return" and the "either outcome is conforming" test license. - CLI signal-wins precedence: scope explicitly to after the run -h / --help short-circuit and usage-level argument parsing. Parser-level usage errors (no target, multiple positionals, duplicate -n/-e, unrecognized flags, etc.) remain parser-level and are not displaced by signal-wins. - `--` grammar: reject `--` in any position in `run` outside the help short-circuit. No POSIX end-of-options support either; added as a Rejected / Deferred Alternative. - §3.2 — Project Root: add to Affected SPEC Sections to make project-root derivation rules (CLI = own process.cwd() without $PWD/realpath; programmatic = resolved RunOptions.cwd or process.cwd() at call time) explicit. - Global env-file path resolution: align timing with env-file loading (first next() for run(), implementation-defined for runPromise()) so XDG_CONFIG_HOME / HOME lookup timing is unambiguous. - CLI inherited-env test: remove the misleading "concurrent process modifies loopx env" claim; make the per-run snapshot mutation test programmatic-only, since POSIX forbids external env mutation. - Cleanup-warning category tokens: require the token in a loopx-controlled prefix position AND require implementations to escape / quote user-controlled text so TMPDIR-influenced paths cannot introduce a second apparent token. Cardinality-of-one remains observable. Status stays Proposed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…snapshot timing, tighten impl-defined scope and CLI grammar terminology Address review-pass feedback. Narrow the "implementation-defined by default" sentence so it cannot be read as de-specifying existing SPEC guarantees outside this ADR's change surface. Rewrite the cleanup-warning "Token placement and user-controlled text" rule: the normative requirement is that user-controlled text cannot contribute an additional plain-text occurrence of any token; prefix placement alone is insufficient when paths are also rendered, and merely surrounding user-controlled text in quotes is not sufficient because a quoted string still contains the token substring. Rename the inherited-env subsection to "per-API split, not uniformly 'lazy'" so the text no longer simultaneously claims run()/runPromise() share lazy semantics while also allowing synchronous call-time capture under runPromise(); update cross-references in §2, §7.2, §9.1/§9.2 accordingly. Add an explicit RunOptions.env enumeration algorithm (Object.entries-equivalent semantics, with observable per-key getOwnPropertyDescriptor probes and captured snapshot errors on throwing probe traps), resolving the ambiguity between "non-enumerable own string keys are ignored" and "one-pass enumeration may invoke per-property traps." Split the CLI §4.1 / §4.2 test recommendation so target-validation failures (loopx run name=value) are not lumped under "usage errors"; tests may no longer require a usage-style diagnostic for that form. Add the throwing-addEventListener subcase to the invalid-options.signal rule and clarify that removeEventListener is not part of the compatibility contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…coping, tmpdir parent, option-first priority, duck-typed signal reentrancy - Fix internal contradiction in §1 "Scope of CLI signal-wins precedence" / §7.3 Affected: pre-handler-installation window no longer claims both "usage error surfaces regardless of signal" and "signals follow POSIX default disposition"; both outcomes are now explicitly conforming and tests must tolerate either. - Reword CLI signal-wins rule around handler observation rather than OS-level delivery, so implementations that run synchronous pre-iteration work are not required to poll / async-ify to meet the "signal wins" contract. - Loosen non-cleanup-warning token rule from "must not contain any of the three tokens" to "must not use them as loopx-controlled category markers", permitting incidental occurrences in user-controlled text (env-file lines, paths) and removing a sanitization burden on every non-cleanup warning site. - Add §1 "Parent directory selection" clarifying that os.tmpdir() is evaluated in the loopx process environment; env-file entries and RunOptions.env do not redirect LOOPX_TMPDIR parent selection. - Pin project-root-blocking / envFile-path-blocking option errors (non-string / throwing options.cwd / options.envFile) ahead of non-options pre-iteration failures in the programmatic-API priority rule; retain implementation-defined ordering for the remaining non-abort bucket. - Add §1 "Duck-typed signal reentrancy" rules: synchronous abort-listener invocation or observed-aborted during capture treats signal as aborted; already-aborted real AbortSignal must be observed as aborted; ordering between reading .aborted and registering listener is otherwise implementation-defined for duck-typed signals only. - Update Scope section to list new implementation-defined caveats (pre-handler-installation signal ordering, delivered-but-unobserved signal vs. synchronous pre-iteration failure, duck-typed signal latitude) and new pinned contract items (project-root-blocking option-error ordering, reserved-as-marker cleanup token scoping). - Update Test Recommendations to match all of the above. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tightening pass on ADR-0004 surfacing work:
- scope summary rule 5 and detailed non-abort priority section so the
pinned options.cwd / options.envFile ordering only beats the four
project-root-dependent failures; relative priority against target
argument / syntax validation is now explicitly implementation-defined
(resolves prior contradiction between summary and detailed text)
- carve the inherited-env snapshot timing and call-time option
snapshotting out of the "pre-iteration runs asynchronously after
return" rule for runPromise(), matching §2's per-API split
- add cleanup idempotence rule (at most one cleanup attempt per created
LOOPX_TMPDIR) so per-run warning cardinality is bounded to one across
racing terminal triggers
- reject function values in RunOptions.env shape, matching the options
parameter's existing function rejection
- simplify TMPDIR / runPromise() guidance to "before calling
runPromise()" since user code cannot mutate between call and return
- drop Deno references — SPEC §1 targets only Node.js and Bun
- clarify loopx run name=value grammar classification ("target, not
named argument" is stable) vs. observable outcome under §7.1, which
may surface a discovery error first in a project without .loopx/
Status remains Proposed pending separate acceptance.
…tion Per review feedback: the ADR was doing the work of an ADR plus a future SPEC patch plus a TEST-SPEC at once. Tightened to focus on the spec changes themselves so the ADR can fully drive the SPEC.md update and then retire from the working set. Specific changes (all per maintainer guidance on the four clarification points raised in review): - v1-scope `--` rejection on `loopx run`: framed as parser simplification arising from "no named-argument tail," not a permanent product stance. Future ADR may revisit alongside a named-argument surface. - Cleanup warning category tokens demoted to implementation-defined. Kept the normative behavior (at most one cleanup attempt per tmpdir, at most one warning per attempt) but dropped the public token contract, cardinality-by-token-match rules, and user-controlled-text escaping rules. Tests assert via provenance, not plain-text token matching. - `runPromise()` inherited-`process.env` snapshot pinned to call-time (synchronous, before return). Removes the previous "implementation- defined, bounded by no-later-than-first-spawn" latitude. `run()` retains lazy capture at first `next()`. Symmetric with `RunOptions.env` and `RunOptions.cwd` capture timing. - `RunOptions.env` one-pass enumeration / per-trap invocation pattern demoted to implementation-defined. Kept "each field read at most once per call, no retry after throws" as the SPEC-level guarantee. Other tightening: - Removed the ~900-word "Scope of this ADR" preamble that locked observable edge-case mechanics as stable contract. - Removed the standalone "Decision Summary" section (its content was duplicated by the §1-§4 decision sections themselves). - Trimmed Test Recommendations from ~95 bullets to ~9 high-risk edge cases. Per ADR-0001 the section is for cases easy to overlook, not an exhaustive test plan. - Promoted CLI grammar from a Decision-Summary bullet to a top-level §5 Decision section so the v1-scoping is obvious.
…ace precedence, tmpdir hardening, §7.4 - Broaden pre-first-next() .return()/.throw() carve-out to suppress all pre-iteration errors (invalid target, target syntax, discovery, env-file loading, target resolution, tmpdir creation) in addition to option-snapshot errors, and fix the "without observing signal state" wording that conflicted with call-time signal capture. - Add catch-all terminal-outcome precedence: first trigger observed by loopx wins among genuinely racing terminal triggers that no explicit precedence rule covers; idempotence and warning cardinality are independent of outcome selection. - Separate RunOptions.env shape validation (programmatic, surfaces under maxIterations: 0) from CLI -n 0 behavior (no RunOptions.env surface) so the "-n 0 validates env shape" claim is no longer misleading. - Pin tmpdir creation order as mkdtemp → identity capture → mode securing, and define per-step creation-failure cleanup (no-op / single rmdir / full cleanup-safety routine) in that order. - Snapshot the tmpdir parent (os.tmpdir() / TMPDIR / TEMP / TMP) on the same schedule as the inherited process.env snapshot: synchronous for runPromise(), at first next() for run(). Eliminates the runPromise() race where a post-return process.env.TMPDIR mutation could have silently affected the tmpdir parent. - Introduce a new §7.4 "Run-scoped temporary directory lifecycle" in the Affected SPEC Sections list, covering parent selection, location/ naming/mode, creation order, identity-fingerprint cleanup safety, renamed-away and mount-point behavior, race-resistance scope, absence of stale-tmpdir reaping, and settlement-based cleanup on run(). - Qualify the incorrect "no existing workflow script uses this pattern" claim: .loopx/shared/dispatch.sh uses cwd-relative ./send-*.sh and ./node_modules/.bin/tsx references that require migration. - Redefine LOOPX_WORKFLOW_DIR as the directory portion of the cached absolute discovery-time script path, making the Bash $(dirname "$0") equality robust to trailing slashes, symlinks, and lexical normalization without recomposing from $LOOPX_PROJECT_ROOT / .loopx / $LOOPX_WORKFLOW. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…loopx install New decision bundled into ADR-0004: loopx install spawns npm install post-commit in each committed workflow with a top-level package.json. Adds --no-install opt-out to install-scoped CLI (§4.2). Retires the existing §10.9 manual-install rule and adds a new §10.10. Rationale surfaced during analysis of how to optimize existing workflow flows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix T-API-55c/55d/65p/65q to construct option objects directly instead of via object-spread, so throwing getters/proxies are preserved as accessors on the object passed to run()/runPromise() rather than being invoked at the test call site. Add a general "test-construction sanity for getter/proxy variants" note in §1.3 explaining the rule. Add T-INST-112h (top-level .gitignore lstat failure other than ENOENT via a new gitignore-lstat-fail seam), T-INST-112i (FIFO .gitignore via gitignore-replace-with-fifo seam), and T-INST-112j (socket .gitignore via gitignore-replace-with-socket seam) to close the previously-tracked SPEC 10.10 safeguard-failure coverage gaps. Update §1.4 seam table and Appendix A row 10.10 accordingly. Create SPEC-PROBLEMS.md with P-0004-02: signal handling during the post-commit auto-install pass when no npm install child is currently active (SPEC 10.10's "Signals during npm install" clause covers only the active-child case). TEST-SPEC.md does not add conformance tests for the no-active-child windows until the clause is clarified. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve P-0004-02 with a SPEC 10.10 clarification covering signal handling during the auto-install pass when no npm child is active, delete SPEC-PROBLEMS.md, fold the resolution note into TEST-SPEC §9, and apply four targeted TEST-SPEC.md refinements: T-API-62f2 and the descriptor-trap variants of T-API-68i / T-API-69h are reframed as observational (descriptor-trap invocation is implementation-defined, not a SPEC requirement) and dropped from direct traceability claims; T-API-51f closes the run() full env-precedence-chain surface gap; T-INST-112k records the regular-but-unreadable .gitignore permission-non-inspection sub-path as a known gap with a recommended seam; and T-TMP-12d / T-TMP-12e known-gap notes now subsume the signal/abort × creation-failure race forms. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Convert T-INST-116h/i/j/k to ordinal pause windows so they no longer assume an unspecified commit order; define the parent-observable JSON marker contract for the LOOPX_TEST_AUTOINSTALL_PAUSE seam; clarify the gitignore-make-unreadable seam's mode-restoration responsibility (loopx leaves mode 000, harness restores in afterEach); add T-TMP-13b for run() generator natural-settlement cleanup, T-TMP-18b for SIGINT escalation + tmpdir cleanup, and T-API-10f-throw for active-child .throw() process-group termination; update Appendix A traceability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds tests / known-gap notes for ADR-0004 coverage edges identified in review: - T-API-66c/d/e + T-TMP-24e/f/g: abort-after-final-yield variants for the `stop: true`-driven final-yield trigger (existing T-API-66/66a/66b + T-TMP-24a/24c/24d only covered the `maxIterations`-reached trigger). - T-API-10c4 + T-API-10c5: live signal that aborts after `run()` / `runPromise()` returns × `maxIterations: 0` (complementing the pre-aborted-signal coverage in T-API-10c2 / T-API-10c3). - T-API-64m + T-API-64m2: duck-signal `addEventListener` getter throws on read (distinct from the function-throws-on-call case in T-API-64f / T-API-64g). - T-INST-116l: known-gap note for the "aggregate report already emitted" carve-out half of SPEC 10.10's signal-termination clause, with implementer note for a `post-aggregate-report` pause-seam value. - T-TMP-35f/g/h: cleanup-warning-does-not-affect-outcome coverage on the signal-terminal (CLI) and abort-terminal (`runPromise()`, `run()`) surfaces. - Tmpdir Parent Snapshot Timing: literal-path expectation preface reinforcing `fs.mkdtemp`-allocated parents over fixed `/tmp/...` placeholders for T-TMP-25 onward. No SPEC.md changes — review found no ADR-0004 ambiguities requiring spec edits, and SPEC-PROBLEMS.md remains absent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Track T-INST-116l (already-emitted aggregate-report carve-out) as a known ADR-0004 gap consistently across §1.3, §9 P-0004-02 resolution note, and the Appendix A SPEC 10.10 row. Fix the T-TMP-12-cli subcase count from "four" to "five". Add run() generator counterparts for env-file NUL spawn failures (T-ENV-26f, T-ENV-26g, T-ENV-27d, T-ENV-27e) so the local/global env-file tier is covered on all three run surfaces. Add T-CLI-RUN-DASHDASH-10/11 to close the "-- as option operand" parser gap (loopx run -e -- ralph and loopx run ralph -e --). Relax T-INST-119 to forbid only actual progress indicators (spinners, progress bars, percentages); plain status lines are not asserted against absent a SPEC 10.10 clarification. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add new tests and strengthen existing ADR-0004 coverage based on review feedback against SPEC.md: - T-API-59b / T-API-59c: run() generator-surface counterparts to T-API-59 / T-API-59a (RunOptions.env does not redirect global env-file path resolution via XDG_CONFIG_HOME / HOME). - T-API-60b / T-API-60c: run() generator-surface counterparts to T-TMP-29b / T-TMP-29c (RunOptions.env does not redirect tmpdir parent via TEMP / TMP). - T-API-65v / T-API-65w: invalid options wrapper + aborted signal intersection on runPromise() and run() — pin down the SPEC 9.3 carve-out that an invalid options value captures no usable signal even when the wrapper carries an aborted AbortSignal. - T-API-51a: strengthen with in-script stat of LOOPX_TMPDIR matching T-TMP-30 / T-TMP-31 rigor (proves the protocol-injected value is the real loopx-created tmpdir, not a string substitution). - T-INST-119 / T-INST-119a / T-INST-119a-stderr / T-INST-119b: tighten npm stdout/stderr passthrough assertions from substring match to exact-standalone-line match, so a buggy implementation that prefixed npm lines (e.g., "[npm] npm-stdout-MARKER\n") is caught. SPEC-PROBLEMS.md remains absent — no ADR-0004-scoped SPEC ambiguity needs to be tracked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Clarify post-exit-first/post-exit:<workflow> seam definition (§1.4) to guarantee the npm child's exit and any non-zero-exit aggregate failure entry are recorded before the pause begins, so T-INST-116j2 actually exercises the "accumulator already holds an npm-non-zero entry" case. - Fix global-env-file SPEC 8.2 → 8.1 references in T-TMP-12-global-env- unreadable, T-TMP-12-cli-global-env-unreadable, T-API-65r, T-API-68o, T-API-69n, and T-SIG-30, plus appendix traceability rows: move T-API-68o, T-API-69n, T-SIG-30 from row 8.2 to row 8.1; add 8.1 to T-TMP-12 and T-TMP-12-cli parent-trailer Spec lists. - Add T-TMP-12f4: starting-workflow unreadable package.json warning runs before tmpdir creation, closing the fourth SPEC 3.2 package.json failure-mode branch (the unreadable-file branch was previously left as an implicit corollary of T-VER-07). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- T-API-65u: drop the throwing-cwd-getter variant. SPEC 9.5 leaves the ordering between reading aborted and registering the duck listener implementation-defined, so an impl that reads aborted (false) and then captures the cwd-getter throw without registering the listener is conformant. The "abort beats option-snapshot failure" axis is already covered for real pre-aborted AbortSignals by T-API-65p / 65q. Keep the env-file and target-resolution variants where pre-iteration timing makes the abort precedence observable independent of intra- snapshot ordering. - T-CLI-RUN-DASHDASH-10/11: replace the "no MARKER leaked into spawned env" assertion (not independently observable when no child spawns) with an absence-of-SPEC-8.1-invalid-key-warning assertion. The "--" file now contains a malformed line "1BAD=warning-if-loaded" so an impl that loaded it before usage validation would emit the SPEC 8.1 warning to stderr regardless of any subsequent spawn. - T-API-56g, T-API-56h: add positive coverage for non-plain RunOptions.env objects. T-API-56g pins the structural-not-nominal contract via a class instance; T-API-56h pins that Map is accepted as a shape but contributes zero env vars (Map entries aren't own enumerable string-keyed properties). - T-INST-113c2: parameterize the multi-workflow malformed-package.json continuation rule over the remaining SPEC 3.2 / 10.10 causes (unreadable, invalid-semver, non-string loopx range value), so the SPEC 10.10 "other workflows still proceed" clause is exercised independently per cause. Trace matrix updated for SPEC 3.2, 8.1, 9.5, 10.10. No SPEC.md or SPEC-PROBLEMS.md changes — feedback explicitly notes no ADR-0004- scoped SPEC ambiguity requires resolution this cycle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds three test groups closing residual ADR-0004 coverage gaps that were identified in the post-acceptance TEST-SPEC review: - T-API-21h/i/j: runPromise() counterparts for call-time relative envFile and cwd resolution (mirroring T-API-21f/g on the run() surface), including the combined relative-cwd × relative-envFile case unique to runPromise()'s eager pre-iteration snapshot. - T-SYM-07b: Bun counterpart for the symlink-free import.meta.url vs. LOOPX_WORKFLOW_DIR byte-for-byte equality from SPEC 6.3, with the symlink-divergence assertion intentionally omitted (SPEC 6.3 does not require Bun to match Node's realpath behavior). - T-CLI-RUN-DASHDASH-12/13: -n operand-position counterparts to T-CLI-RUN-DASHDASH-10/11, closing the "-- cannot slip through as an option operand" axis for the second run option that consumes an operand. Also updates the Appendix A traceability matrix rows 4.1, 4.2, 6.1, 6.3, 9.2, 9.5, and 12 to reference the new test IDs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Fix T-MOD-03h / T-MOD-03h-bun extension-remapping reliance: import the nested helper as ./lib/helper.ts (its actual extension) instead of ./lib/helper.js, since SPEC does not specify tsx/Bun .js→.ts remapping. - Promote the optional run() concurrent-isolation companion in T-API-50f to a required test T-API-50g, pinning ADR-0004's no-racy-process.env- mutation motivation on both API surfaces. - Expand T-API-65p / T-API-65q (abort-precedence × option-snapshot) with the full enumerated invalid maxIterations set (Infinity, null, "1" added to -1, 1.5, NaN) and reword "all remaining ... failures" to "representative remaining ... failures" for the env shape/value branches, deferring exhaustive env-shape coverage to T-API-53–55 etc. - Apply the same expansion + rewording to the carve-out tests T-API-68i (.return()) and T-API-69h (.throw()). - Parameterize T-API-55a / T-API-55b over the full SPEC 9.5 invalid-env shape and entry-value matrix under maxIterations: 0, ensuring shape validation surfaces under the zero-iteration short-circuit on both API surfaces. No SPEC.md changes; no SPEC-PROBLEMS.md added (no ADR-0004-scoped ambiguity identified by this review cycle). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Fix T-CLI-RUN-DASHDASH-08 and T-TMP-12-cli-usage / T-TMP-12-cli-help-with-unknown wording so help short-circuit tests no longer assert "no discovery"; SPEC 11.2 explicitly permits non-fatal run-help discovery/validation. Frame the assertions around "does not enter the execution pre-iteration sequence" and "no LOOPX_TMPDIR" instead.
- Broaden T-API-57b ("=" in RunOptions.env key) to assert only that loopx does not reject as option-shape error and that the spawn either fails or succeeds — drop the over-pinned "variable is observable" branch since runtime parsing of "BAD=KEY" is OS/runtime-dependent.
- Add T-API-72a covering runPromise() inherited-env snapshot reuse across iterations: mutate process.env.MYVAR between iterations under a release-file sentinel and assert both spawns observed the call-site snapshot.
- Add T-INST-110g pinning down auto-install on a tarball source — previous positive-trigger tests are source-type-agnostic in wording but may default to git fixtures, leaving the post-commit auto-install pass on the tarball path uncovered.
- Extend T-API-10h to observe LOOPX_TMPDIR via an external marker and assert tmpdir cleanup runs before generator settlement under SIGKILL escalation, closing the gap between T-TMP-21 (no escalation) and T-API-10g (.return() escalation).
- Strengthen T-TMP-12a / T-TMP-12d / T-TMP-12e with explicit "no cleanup-related stderr warning" assertions on the success-cleanup branches, pairing inversely with T-TMP-12d2 / T-TMP-12e2's positive cleanup-warning assertions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address reviewer feedback on TEST-SPEC.md against SPEC.md (ADR-0004 scope): - Fix T-API-50g deadlock: split out un-awaited next() promises so the harness can wait for fixture markers and touch release files before awaiting the first yields, matching T-API-50f's drive sequence. - Clarify withFakeNpm PID observability: add explicit pidFile?: string option to FakeNpmOptions and document that per-invocation log entries are finalized at shim exit (so tests needing alive-shim PIDs use the pidFile, not the log). Updated T-INST-116, T-INST-116c, T-INST-116e, T-INST-116f, T-INST-116g, T-INST-119a, and T-INST-119a-stderr. - Replace "fsync stderr stream" wording in the post-aggregate-report seam (and its T-INST-116l / resolved-this-cycle references) with "complete/flush the stderr write as far as the runtime stream API supports" — fsync(2) on a pipe is not portable and stderr is commonly a pipe in tests; fsync remains the marker-file flush requirement. - Add an implementation-neutral cleanup-warning detection harness rule to section 4.7's LOOPX_TMPDIR preface so "exactly one cleanup-related warning" assertions across T-TMP-35*, T-TMP-36*, T-TMP-38*, T-TMP-40, T-TMP-41, T-TMP-42, T-TERM-03, T-INST-116l, etc. have a concrete predicate (test-only structured marker, single-extra-stderr-line counting, or known-marker subtraction) that does not pin warning text. No SPEC.md changes were proposed by the feedback and none are made; SPEC-PROBLEMS.md remains absent (no ADR-0004-scoped ambiguities). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add T-TMP-08b CLI same-project concurrent tmpdir isolation test, clarify T-API-55e wording around the wrapper-shape gate firing before the maxIterations field is read, and pin T-INST-110g's archive-derived workflow naming so <name> placeholders are unambiguous. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address three reviewer items scoped to ADR-0004: 1. T-API-55e: drop the over-pin on implementation-defined pre-iteration priority (SPEC 9.3). The previous fixture combined a syntax-invalid target and a missing-`.loopx/` discovery failure with the invalid `options` wrapper, asserting wrapper-shape rejection wins — but SPEC leaves that priority implementation-defined. Rewritten to use a valid project + valid target so the wrapper-shape rejection is the only conforming surface, and reframed the `maxIterations: 0` framing (wrapper-shape validation runs before field-level processing, so the zero-iteration short-circuit is not applicable to this case). 2. Add T-TMP-12e3 covering `mode-secure-fail` × `lstat-fail` — the second cleanup-safety failure branch reachable from creation-failure handling under SPEC 7.4. Updated the section preamble and the section 1.4 seam description to clarify which cleanup-fault values are reachable when composed with `mode-secure-fail` (`lstat-fail` and `recursive-remove-fail` reachable; `symlink-unlink-fail` unreachable because the partial tmpdir is never a symlink — documented as a known gap that would need a separate seam). 3. SPEC §9.5 enumerates `Proxy ownKeys` traps, throwing enumerable getters, and throwing `options.env` getters as snapshot-time-throw paths but does not pin down whether the value-read step uses ordinary `[[Get]]` semantics (which invokes a Proxy `get` trap) or descriptor-based extraction (which does not). Added SPEC-PROBLEMS.md tracking the ambiguity and relaxed T-API-62f3 (throwing `get` trap surfacing), T-API-62h9 (no-retry counter on `get` trap), and the value-read assertions in T-API-52e / T-API-52e2 variant (b) to observational status, matching the precedent set by T-API-62f2 for the analogous descriptor-trap ambiguity. T-API-62f / T-API-62h5 / T-API-62h6 remain strict pins on the SPEC-pinned `ownKeys` axis. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve the open ADR-0004-scoped SPEC ambiguity around RunOptions.env Proxy get trap semantics by amending SPEC §9.5 / §9.1 to specify ordinary [[Get]] semantics for value reads (option 1 from SPEC-PROBLEMS.md). Promote T-API-62f3 / T-API-62h9 / T-API-52e / T-API-52e2 from observational to strict conformance pins per the new SPEC clause, and delete SPEC-PROBLEMS.md (no remaining open ADR-0004 problems). Make the structured cleanup-warning marker (LOOPX_TEST_CLEANUP_WARNING) a required test-only seam in section 1.4 so cleanup-warning cardinality tests can reliably distinguish cleanup warnings from implementation- defined creation-failure / script-failure errors on mixed-stderr terminals (T-TMP-12d2 / T-TMP-12e2 / T-TMP-12e3 / T-TMP-35c–35e / T-TMP-40 / T-TMP-41 / T-TMP-42 / T-TMP-42a / T-TMP-42b / racing-trigger warning-cardinality). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address four feedback items from the review of ADR-0004 TEST-SPEC.md coverage: 1. List the cleanup-safety symlink-`unlink` branch within creation-failure handling under `mode-secure-fail` as a known gap in the section 1.3 inline list and the Appendix A 7.4 row, since the partial directory created by `mkdtemp` is never a symlink and cleanup-safety rule-2 dispatch is unreachable in that composition without an additional swap-to-symlink seam. 2. Remove the stale "excluding the known-gap IDs T-TMP-12d / 12e / 38 / 39" exclusion clause from the Appendix A 7.4 row (those tests are now seam-backed direct conformance pins, not gaps), and add T-TMP-12e3 to the section 1.3 "previously seam-dependent gaps promoted to direct pins" summary. 3. Add T-TMP-38d2 — the symmetric counterpart to T-TMP-38d on the inverted observation order (post-final-yield consumer `.throw()` observed first, racing abort during cleanup-start). Closes the matrix-symmetry gap on the warning-cardinality axis of SPEC 7.2's "abort after final yield concurrent with consumer `.throw()`" enumeration. Trace into Appendix A 7.2 / 7.4 / 9.1 / 9.3 rows. 4. Clarify the `withFakeNpm` `logFile` field contract so the shim is required to install a Bash `EXIT` trap that finalizes the per-invocation log entry under SIGINT / SIGTERM termination, matching the assertions in T-INST-116b / 116b2 / 116j / 116j2. SIGKILL remains intentionally uncovered (no userspace trap runs); the relevant escalation tests (T-INST-116c / 116f) assert on PID termination instead of the exit-time log. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Fix T-TMP-38d2 outcome assertion to silent clean completion (done: true) per SPEC 9.1's no-active-child consumer-cancellation rule, aligning with T-TMP-22d / T-TMP-22f. - Move LOOPX_TEST_CLEANUP_WARNING structured marker seam into section 1.4 Internal Test Seams; leave section 4.7 as a reference back to it. - Replace Appendix A row 13's stale "T-TMP-12d/12e/38/39 known-gap" exclusion with the actual residual LOOPX_TMPDIR known gaps (T-TMP-43, T-TMP-44, T-SIG-29, T-SIG-30b / T-API-10j). - Add T-API-64n / T-API-64n2: prototype-inherited duck-signal acceptance pinning SPEC 9.5's "expose" wording against own-property-only readings. - Add T-INST-116h2 / 116i2 / 116k2 / 116l2: SIGTERM-axis parity for the no-active-child auto-install windows; SPEC 10.10 names "SIGINT / SIGTERM" together for these windows. - Add T-TMP-38a2: mid-loop .return()-first vs. abort-during-cleanup cleanup-warning cardinality test, completing matrix symmetry on the .return() axis (counterpart to T-TMP-38a). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add tests for previously uncovered API surfaces (run() generator
counterparts to runPromise()-only coverage), extend tier coverage of
local-env-file non-redirection of global env-file lookup, and clarify
T-INST-110's coverage scope around the SPEC 10.10 "sequentially in commit
order" requirement.
- T-TMP-11a: run() generator zero-iteration tmpdir non-creation
- T-TMP-08c: concurrent run() generator tmpdir isolation (closes the
four-cell {independent / same project} x {generator / promise / CLI}
matrix)
- T-API-21e2: run() generator counterpart to T-API-21e (absolute envFile)
- T-API-59d / T-API-59e: local envFile does not redirect global env-file
lookup via XDG_CONFIG_HOME / HOME (extends T-API-59 series from
RunOptions.env tier to local-env-file tier)
- T-TMP-11 / T-TMP-08a / T-API-21e: clarify each is runPromise-specific
- T-INST-110: clarify that the test pins sequentiality but not the
auto-install-order-equals-file-commit-order relation, which is not
externally observable in SPEC
Appendix A traceability rows updated for SPEC 7.4, 8.1, 8.2, 8.3, 9.1,
9.2, 9.5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes five surface-parity / cleanup-trigger gaps surfaced in this
review cycle:
- T-TMP-16g/h/i: cleanup on bare-name goto resolving to missing script
in the current workflow, across CLI / runPromise / run surfaces
(complements T-TMP-16a–f's qualified-target form).
- T-TMP-16j: cleanup on goto whose target violates the SPEC 4.1
name-restriction pattern (complements T-TMP-16b's delimiter-syntax
branch on the syntactic-invalidity axis).
- T-INST-116j3: SIGTERM-axis parity for T-INST-116j2 on the
post-exit-first × non-zero-npm-exit composed window.
- T-API-56i: representative run()-surface coverage of the SPEC 9.5
RunOptions.env filtering and structural-shape-acceptance matrix.
- T-API-64a2: run()-surface own-property duck-signal acceptance,
closing the {own / prototype-inherited} × {run / runPromise} matrix.
Coverage matrix rows for SPEC 4.1, 7.2, 7.3, 7.4, 9.1, 9.2, 9.3, 9.5,
10.10, and 12 updated to reference the new tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply feedback identifying gaps in TEST-SPEC.md against SPEC.md:
- Extend T-API-65p / T-API-65q abort-precedence variants to cover
throwing `env` proxy `get` trap on an included key (variant xv)
and throwing `options.maxIterations` getter (variant xvi).
- Extend T-API-55c / T-API-55d zero-iteration snapshot-throw matrix
with throwing `env` proxy `get` trap on an included key (variant d).
- Add `LOOPX_TEST_AUTOINSTALL_PAUSE=post-spawn-failure-first` ordinal
window value plus the corresponding name-targeted form, and add
T-INST-116m / T-INST-116m2 (SIGINT / SIGTERM) for the no-active-child
signal contract on the npm-install-spawn-failure accumulator state.
- Add T-TMP-38f for SIGTERM-first racing-signal cleanup-idempotence
parity (inverted observation order of T-TMP-38).
- Add T-SYM-02d for CLI symlinked-project-root effective-cwd
device/inode identity, completing the {string-spelling, identity} ×
{CLI, programmatic} matrix.
- Clarify T-TMP-38e tmpdir-path observation: harness scans the
test-isolated TMPDIR parent for the single loopx-* entry left
behind by `LOOPX_TEST_CLEANUP_FAULT=recursive-remove-fail`.
- Update Appendix A traceability matrix entries for sections 6.1,
7.2, 7.3, and 10.10 to reference the new tests.
No SPEC.md or SPEC-PROBLEMS.md changes — feedback identified no
ADR-0004 SPEC ambiguities blocking clean test coverage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply post-acceptance feedback covering five areas: tighten T-INST-116i / 116i2 with a pre-signal lstat+content snapshot of the current workflow's .gitignore so the SPEC 10.10 "side effects completed before the signal observation remain on disk" rule is pinned without over-specifying the safeguard-write timing window; add T-TMP-42c (cleanup-fault × CLI signal × all three LOOPX_TEST_CLEANUP_FAULT seam values × both signals) closing the remaining diagonal in the cleanup-warning-does-not-affect-outcome matrix; pin the SPEC 10.10 "no aggregate report when no failures" clause via explicit negative assertions on T-INST-110 and T-INST-110c; introduce a suite-wide env-absence robustness rule in section 4.7; and add T-API-51a2 (generator-surface counterpart for all five protocol variables) and a PWD passthrough assertion in T-INST-115 for matrix symmetry. Open SPEC-PROBLEMS.md with P-0004-01 to track auto-install commit-order observability for a follow-up SPEC clarification cycle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve P-0004-01 (auto-install commit-order observability) by amending SPEC §10.10's "Trigger" bullet to make cross-workflow auto-install order implementation-defined and not an external conformance contract. Delete SPEC-PROBLEMS.md (P-0004-01 was the only entry). Update TEST-SPEC.md to drop "commit order" framing in T-INST-110, withFakeNpm comments, the LOOPX_TEST_AUTOINSTALL_PAUSE seam description, T-INST-114, T-INST-114b, T-INST-114d, T-INST-112c, T-INST-112h, T-INST-116b/b2/h/i/j/j2/j3/k/l/m, Section 9, and Appendix A in favor of "implementation-defined auto-install order." Add T-TMP-27a covering SPEC 9.2's "LOOPX_TMPDIR is created asynchronously after `runPromise()` returns" clause via a synchronous readdir snapshot taken on the same microtask tick as `runPromise()`'s return. Add T-API-59f and T-API-59g (CLI `-e` parity for the SPEC 8.1 "inherited environment" rule across XDG_CONFIG_HOME and HOME), extending the local-env-file-does-not-redirect-global-env-file-lookup coverage from the runPromise() surface (T-API-59d/e) to the CLI surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.