Skip to content

Rectify: research recipe archives wrong experiment directory; replace find heuristic with context tracking (#655)#658

Merged
Trecek merged 9 commits intointegrationfrom
research-recipe-archives-wrong-experiment-directory-replace/655
Apr 7, 2026
Merged

Rectify: research recipe archives wrong experiment directory; replace find heuristic with context tracking (#655)#658
Trecek merged 9 commits intointegrationfrom
research-recipe-archives-wrong-experiment-directory-replace/655

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented Apr 7, 2026

Closes #655

Summary

Replaces the fragile find | sort | tail -1 heuristic in research.yaml with deterministic context.research_dir tracking. Adds two new semantic rules (run-cmd-emit-alignment, run-cmd-find-rediscovery) to catch this class of bug at validation time.

Changes

  • research.yaml: create_worktree emits research_dir into context; commit_research_artifacts uses it directly; create_artifact_branch checkout scoped to specific experiment dir; post-compression guard added; open_artifact_pr body made dynamic
  • src/autoskillit/recipe/rules_cmd.py: two new semantic rules registered in __init__.py
  • tests/recipe/test_rules_cmd.py: 7 new tests for the semantic rules
  • tests/recipe/test_research_artifact_archive.py: 7 new tests for context tracking and guard behavior

Trecek added 3 commits April 7, 2026 11:55
Adds test_rules_cmd.py with 7 tests for the new run-cmd-emit-alignment
and run-cmd-find-rediscovery semantic rules, and extends
test_research_artifact_archive.py with 7 tests covering the research_dir
echo/capture contract, find-heuristic removal, post-compression guard,
and scoped checkout in create_artifact_branch. All tests fail until
rules_cmd.py and research.yaml are fixed.
…rchive path

Adds rules_cmd.py with two semantic rules:
- run-cmd-emit-alignment (ERROR): every non-raw capture key in a run_cmd step
  must have a matching echo "KEY=..." in the cmd; catches silent empty captures
- run-cmd-find-rediscovery (WARNING): flags find|sort|tail heuristics that
  signal an upstream step failed to capture a path into context

Fixes research.yaml:
- create_worktree now emits and captures research_dir so the exact directory
  path flows through context without re-discovery
- commit_research_artifacts uses ${{ context.research_dir }} directly instead
  of find|sort|tail -1 (which picked the wrong dir when multiple existed)
- Adds post-compression guard: fails loudly if artifacts.tar.gz is absent,
  uncompressed dir still present, or README.md is missing
- create_artifact_branch scopes the checkout to the specific experiment subdir
  via basename, preventing blanket research/ copy
- open_artifact_pr detects at runtime whether tarball or raw artifacts/ exists
Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit PR Review — Verdict: changes_requested (COMMENT mode: cannot request changes on own PR)

Comment thread src/autoskillit/recipe/rules_cmd.py Outdated
if not isinstance(cmd, str):
continue
for cap_key, cap_val in step.capture.items():
m = _RESULT_CAPTURE_RE.search(cap_val)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] defense: If step.capture is None (a step with no capture block), calling step.capture.items() will raise AttributeError. Add a None-guard: if not step.capture: continue before the loop.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. In schema.py, RecipeStep.capture is declared as capture: dict[str, str] = field(default_factory=dict). The default_factory=dict guarantees the field is always an empty dict, never None. Calling step.capture.items() cannot raise AttributeError.

result_key = m.group(1)
if result_key in _RAW_RESULT_FIELDS:
continue
# Check that the cmd emits `echo "result_key=..."`.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] slop: Inline comment # Check that the cmd emits \echo "result_key=..."`.` restates exactly what the next two lines do without adding any reasoning about why. Remove it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagged for design decision. This inline comment was classified below the warning threshold (cosmetic/slop). Deferring to human review — no automatic change applied.

if result_key in _RAW_RESULT_FIELDS:
continue
# Check that the cmd emits `echo "result_key=..."`.
echo_pattern = re.compile(rf'\becho\s+"?{re.escape(result_key)}=')
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] bugs: The echo_pattern r'\becho\s+"?{result_key}=' allows an optional double-quote but not a single-quote. A cmd using echo 'KEY=value' (single-quoted) will not match, producing a false-positive alignment error. Update pattern to r'\becho\s+[\"\\']?{result_key}=' to accept both quote styles.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. The rule enforces a documented double-quoted echo convention. The error message prescribes echo "result_key=${...}" as the required form, and the rule description states echo "K=...". This validator intentionally rejects single-quoted cmds that deviate from the documented contract; widening the pattern would silently pass non-conforming recipes.

Comment thread src/autoskillit/recipes/research.yaml Outdated
Comment thread src/autoskillit/recipes/research.yaml Outdated
Comment thread tests/recipe/test_research_artifact_archive.py
from __future__ import annotations

from autoskillit.recipe.validator import run_semantic_rules
from tests.recipe.conftest import _make_workflow
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] tests: Importing the private helper _make_workflow directly from tests.recipe.conftest creates brittle coupling — any conftest refactor silently breaks this import. Expose it as a fixture or move it to a shared test utility module.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. Direct import of _make_workflow from tests.recipe.conftest is the established pattern across the entire tests/recipe/ directory: test_rules_worktree.py, test_validator.py, test_rules_dataflow.py, and test_rules_structure.py all use the identical import. The underscore prefix signals it is not a pytest fixture, not that it is private. The comment misreads a deliberate, widely-replicated convention as brittleness.

Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit review found 8 blocking issues. See inline comments. (verdict: changes_requested — unable to formally request changes on own PR)

Trecek and others added 5 commits April 7, 2026 13:15
…nsitivity

tests/infra/test_claude_md_critical_rules.py and test_docstring_labels.py
used Path(__file__).parent.parent.parent (and bare relative paths like
Path("CLAUDE.md")) which depend on CWD being the project root at fixture
execution time. In CI with xdist, monkeypatch.chdir(tmp_path) calls in
neighboring infra tests (test_quota_check.py) run on the same worker and
can leave CWD temporarily changed; if __file__ is resolved as a relative
path by the pytest import machinery, REPO_ROOT becomes Path(".") and file
reads pick up the wrong location.

Fix: use Path(__file__).resolve() so REPO_ROOT is always an absolute path
regardless of CWD or import mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Trecek Trecek enabled auto-merge April 7, 2026 21:06
@Trecek Trecek added this pull request to the merge queue Apr 7, 2026
Merged via the queue into integration with commit b8479a4 Apr 7, 2026
2 checks passed
@Trecek Trecek deleted the research-recipe-archives-wrong-experiment-directory-replace/655 branch April 7, 2026 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant