Skip to content

Implementation Plan: P2-WP4 Create research-archive.yaml Sub-Recipe#1979

Merged
Trecek merged 10 commits into
developfrom
p2-wp4-create-research-archive-yaml-sub-recipe/1703
May 6, 2026
Merged

Implementation Plan: P2-WP4 Create research-archive.yaml Sub-Recipe#1979
Trecek merged 10 commits into
developfrom
p2-wp4-create-research-archive-yaml-sub-recipe/1703

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented May 6, 2026

Summary

Create src/autoskillit/recipes/research-archive.yaml as a standalone sub-recipe that extracts the 9-step archival phase from research.yaml (lines 855–963). The critical change from the parent recipe: all ingredient-sourced values (pr_url, worktree_path, research_dir, base_branch) use inputs.X references instead of context.X, since these are declared ingredients in the standalone recipe rather than step-captured context variables. Step-captured values (experiment_branch, artifact_branch, artifact_pr_url, archive_tag) correctly remain as context.X. Pack declarations are [github, ci] (the archival phase only needs GitHub CLI and CI tools, not the full research pack). No autoskillit_version field — consistent with bundled recipe policy (removed in #1950). Only 4 ingredients: 3 campaign-sourced hidden (worktree_path, research_dir, pr_url) and 1 user-input (base_branch). The report_path_after_finalize and source_dir ingredients from the parent recipe are omitted because no archival step references them.

Closes #1703

Implementation Plan

Plan file: /home/talon/projects/autoskillit-runs/impl-20260505-213323-163152/.autoskillit/temp/make-plan/p2_wp4_create_research_archive_yaml_sub_recipe_plan_2026-05-05_213600.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step count uncached output cache_read peak_ctx turns cache_write time
plan 1 7.7k 18.2k 493.3k 76.6k 98 53.7k 9m 51s
verify 1 39 11.0k 1.1M 79.2k 118 66.4k 7m 29s
implement 1 1.3M 13.2k 1.2M 31.9k 110 34.7k 5m 44s
prepare_pr 1 68 4.5k 218.4k 35.8k 18 23.5k 1m 42s
compose_pr 1 59 2.2k 159.3k 26.0k 15 13.2k 47s
review_pr 2 730 77.7k 1.5M 83.3k 109 140.1k 18m 47s
resolve_review 2 610 42.4k 4.1M 97.6k 190 152.1k 18m 43s
ci_conflict_fix 1 139 6.6k 599.4k 48.1k 44 35.2k 2m 7s
Total 1.3M 175.8k 9.4M 97.6k 518.9k 1h 5m

Token Efficiency

Step LoC Changed cache_read/LoC cache_write/LoC output/LoC
plan 0
verify 0
implement 339 3548.4 102.4 39.1
prepare_pr 0
compose_pr 0
review_pr 0
resolve_review 36 113253.1 4225.4 1176.6
ci_conflict_fix 545 1099.8 64.5 12.1
Total 920 10241.5 564.0 191.1

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 thread src/autoskillit/recipes/research-archive.yaml
create_artifact_branch:
tool: run_cmd
with:
cmd: "bash scripts/recipe/create_artifact_branch.sh '${{ inputs.worktree_path }}' '${{ context.experiment_branch }}' '${{ inputs.base_branch }}' '${{ inputs.research_dir }}'"
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.

[critical] defense: Shell injection: '${{ context.experiment_branch }}' is captured from git stdout and passed as a single-quoted shell arg. A branch name with a single-quote character breaks the command. Applies similarly to context.artifact_branch (L80), context.artifact_pr_url (L80, L91), context.archive_tag (L91). Values derived from external data should be validated before shell interpolation.

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.

Valid observation — flagged for design decision. Git branch names cannot technically contain single-quote characters (git enforces naming rules), so this path is not exploitable with valid branches. However, hardening quoting across all recipes consistently is a valid project-wide decision worth making deliberately. Flagged for human review.

Comment thread src/autoskillit/recipes/research-archive.yaml
capture_experiment_branch:
tool: run_cmd
with:
cmd: "git -C '${{ inputs.worktree_path }}' rev-parse --abbrev-ref HEAD"
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: Single-quoted shell substitution: '${{ inputs.worktree_path }}' protects against word-splitting but not against paths containing single-quote characters. A worktree_path like /tmp/it's/here would break the command. Same pattern on L69, L70, L80, L81, L91, L92, L105, L106.

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.

Valid observation — flagged for design decision. Worktree paths are system-generated by campaign dispatch and won't contain single quotes in practice. All other bundled recipes use the same single-quote interpolation for context variables. Hardening quoting project-wide is a valid decision to make deliberately rather than per-recipe. Flagged for human review.

Comment thread src/autoskillit/recipes/research-archive.yaml
Comment thread src/autoskillit/recipes/research-archive.yaml Outdated
Comment thread src/autoskillit/recipes/research-archive.yaml
Comment thread tests/recipe/test_research_archive_recipe.py
Comment thread tests/recipe/test_research_archive_recipe.py Outdated
Comment thread tests/recipe/test_research_archive_recipe.py
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: changes_requested — 2 critical blocking issues found; see inline comments for details.

Blocking (critical):

  • research-archive.yaml:104 — ARCHIVE_TAG used in printf but never assigned; close comment body will have an empty archive tag
  • research-archive.yaml:69 — Context values captured from external sources (git stdout) used as single-quoted shell args without sanitization

Warnings:

  • research-archive.yaml:129 — escalate_stop is a defined stop step with no route pointing to it (unreachable)
  • research-archive.yaml:56 — run_cmd steps omit timeout; network-bound gh calls can hang indefinitely
  • research-archive.yaml:58 — Single-quoted shell substitution does not protect against single-quote chars in path values
  • research-archive.yaml:73 — Captured context values (artifact_branch, artifact_pr_url) have no guard against empty capture
  • research-archive.yaml:12 — Summary field omits escalate_stop terminal path
  • research-archive.yaml:49 — begin_archival note overly verbose
  • test_research_archive_recipe.py:12 — class-scoped fixture: verify recipe object is picklable for xdist
  • test_research_archive_recipe.py:18 — test_loads_without_exception is redundant
  • test_research_archive_recipe.py:173 — escalate_stop test does not assert reachability

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: approved_with_comments

Comment thread tests/recipe/test_research_archive_recipe.py
Comment thread tests/recipe/test_research_archive_recipe.py
Comment thread tests/recipe/test_research_archive_recipe.py
Comment thread tests/recipe/test_research_archive_recipe.py
capture:
archive_tag: "${{ result.archive_tag }}"
on_success: close_experiment_pr
on_failure: patch_token_summary
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: context.archive_tag captured from result.archive_tag without non-empty validation. If tag_experiment_branch.sh succeeds but emits no archive_tag key, downstream steps (close_experiment_pr L104) embed an empty string in the gh pr close comment body, producing a malformed reference silently.

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.

Valid observation — flagged for design decision. The concern is real: context.archive_tag is captured from result.archive_tag without a non-empty guard, and close_experiment_pr (L104) embeds it in a shell printf. However, the RecipeStep schema has no on_empty_result, required_keys, or similar validation construct — such a field does not exist in the schema or any bundled recipe. The recipe's declared intent is best-effort degradation (failures route to patch_token_summary), and on_failure covers script-level exits; an empty-key-but-exit-0 gap would require either adding validation inside tag_experiment_branch.sh or introducing a new schema feature. Both require a design decision.

capture:
artifact_pr_url: "${{ result.artifact_pr_url }}"
on_success: tag_experiment_branch
on_failure: patch_token_summary
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: context.artifact_pr_url captured from result.artifact_pr_url without non-empty validation. If open_artifact_pr.sh succeeds but emits no artifact_pr_url key, tag_experiment_branch (L91) and close_experiment_pr (L103) receive an empty string in shell substitutions, producing silently incorrect tag metadata and a blank PR reference.

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.

Valid observation — flagged for design decision. The concern is real: context.artifact_pr_url is captured from result.artifact_pr_url without a non-empty guard, and both tag_experiment_branch (L91) and close_experiment_pr (L103) embed it in shell substitutions. However, the RecipeStep schema has no on_empty_result or required_keys mechanism. The run-cmd-emit-alignment rule explicitly exempts bash scripts/ invocations (which is the pattern used here). Remediation requires adding validation inside open_artifact_pr.sh or introducing a new schema feature — both are design-level decisions.

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: warning-only findings detected. See inline comments — no blocking changes required.

Trecek and others added 10 commits May 5, 2026 22:56
Extracts the 9-step archival phase from research.yaml into a
standalone sub-recipe. Key design: all ingredient-sourced values
(pr_url, worktree_path, research_dir) use inputs.X references instead
of context.X since they are declared ingredients in the standalone
recipe. Step-captured values (experiment_branch, artifact_branch,
artifact_pr_url, archive_tag) correctly remain as context.X.

Pack declarations are [github, ci] — the archival phase only needs
GitHub CLI and CI tools, not the full research pack.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The note referenced "context.pr_url" in explanatory text, which caused
test_no_context_pr_url_in_recipe (raw file text scan) to fail even though
context.pr_url was not used as a variable reference. Rephrased to say
"ingredient (not a captured context value)" instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
research-archive.yaml was added as a new bundled sub-recipe but the
test_bundled_recipe_count_is_13 guard was not updated to include it.
…note

- patch_token_summary.on_failure now routes to escalate_stop instead of
  research_complete — makes escalate_stop reachable (was a dead step)
- summary updated to show '| escalate' alternate terminal path
- begin_archival note: removed verbose implementation-detail sentence

Addresses review comments 3193166853 (unreachable escalate_stop),
3193166858 (summary omits escalate_stop), 3193166860 (over-verbose note).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bility test

- Remove test_loads_without_exception (redundant — fixture failure gives clear errors)
- test_patch_token_summary_routes_to_complete: update on_failure assertion to
  escalate_stop (reflects the wired routing from this PR's recipe fix)
- Add test_escalate_stop_is_reachable: asserts at least one step routes to
  escalate_stop (stronger signal than confirming the step exists alone)

Addresses review comments 3193166862 (redundant test), 3193166865 (weak reachability).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… covered by test_kitchen_rules_forbid_native_tools
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Trecek Trecek force-pushed the p2-wp4-create-research-archive-yaml-sub-recipe/1703 branch from 2c31c4e to e56b0b7 Compare May 6, 2026 05:58
@Trecek Trecek added this pull request to the merge queue May 6, 2026
Merged via the queue into develop with commit 85c4f38 May 6, 2026
2 checks passed
@Trecek Trecek deleted the p2-wp4-create-research-archive-yaml-sub-recipe/1703 branch May 6, 2026 06:14
Trecek added a commit that referenced this pull request May 8, 2026
…1979)

## Summary

Create `src/autoskillit/recipes/research-archive.yaml` as a standalone
sub-recipe that extracts the 9-step archival phase from `research.yaml`
(lines 855–963). The critical change from the parent recipe: all
ingredient-sourced values (`pr_url`, `worktree_path`, `research_dir`,
`base_branch`) use `inputs.X` references instead of `context.X`, since
these are declared ingredients in the standalone recipe rather than
step-captured context variables. Step-captured values
(`experiment_branch`, `artifact_branch`, `artifact_pr_url`,
`archive_tag`) correctly remain as `context.X`. Pack declarations are
`[github, ci]` (the archival phase only needs GitHub CLI and CI tools,
not the full `research` pack). No `autoskillit_version` field —
consistent with bundled recipe policy (removed in #1950). Only 4
ingredients: 3 campaign-sourced hidden (`worktree_path`, `research_dir`,
`pr_url`) and 1 user-input (`base_branch`). The
`report_path_after_finalize` and `source_dir` ingredients from the
parent recipe are omitted because no archival step references them.

Closes #1703

## Implementation Plan

Plan file:
`/home/talon/projects/autoskillit-runs/impl-20260505-213323-163152/.autoskillit/temp/make-plan/p2_wp4_create_research_archive_yaml_sub_recipe_plan_2026-05-05_213600.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code) via
AutoSkillit
<!-- autoskillit:pipeline-signature
steps=prepare_pr,run_arch_lenses,compose_pr,annotate_pr_diff,review_pr
-->

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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