Commit 2ae4bc8
* feat: add deletion regression guards for PR merge pipeline
Adds two targeted guards that detect when a stale PR reintroduces
code deliberately deleted on the base branch:
1. merge-pr/SKILL.md — Step 1.5: Deletion Regression Scan
- Runs for ALL PRs before any merge attempt
- Uses git merge-base + --diff-filter=D/M to find base-branch deletions
- Cross-references PR additions against deleted files and symbols
- Forces conflict report path with ## Deletion Regressions section
- Emits deletion_regression=true/false output token in Step 5
2. review-pr/SKILL.md — Step 2.5 + 7th audit subagent
- Pre-computes deletion context (merge_base, deleted_files, deleted_symbols)
- Adds deletion_regression as 7th parallel audit dimension in Step 3
- Subagent flags regressions as severity=critical, requires_decision=false
- Routes to verdict=changes_requested for automated remediation
3. tests/skills/test_deletion_regression_guards.py — structural guards
- 13 tests asserting both skills have required sections and instructions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(report_bug): include session diagnostics in auto-filed GitHub issues
Add _read_session_diagnostics and _format_diagnostics_section helpers to
tools_integrations.py. Wire them into _run_report_session (new log_dir param)
and _file_or_update_github_issue (new diag param) so that proc traces,
anomaly records, and peak metrics from flush_session_log are appended to
new issue bodies (full) and duplicate comments (condensed). Diagnostics are
gracefully skipped for empty/fallback session IDs or missing directories.
Add 17 tests: 7 for _read_session_diagnostics, 6 for _format_diagnostics_section,
and 4 integration tests validating the full report_bug flow.
* fix: correct test boundary detection edge cases in skill SKILL.md structure
- merge-pr Step 1.5: swap 'if regressions found' before 'if no regressions'
so 'conflict report' text precedes the first 'Step 2' occurrence that the
test uses as a section boundary
- review-pr Step 2.5: remove 'Step 3' and deletion_regression (underscore)
from the intro so the section boundary includes the full bash code block
(--diff-filter=D and MERGE_BASE are now within the detected section)
- review-pr Step 3: move deletion_regression out of JSON schema union so its
first occurrence is in item 7 (immediately followed by severity/
requires_decision fields within the 500/600-char test window)
- All 13 tests in test_deletion_regression_guards.py now pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: remove literal 'Step 3.5' and 'Step 4' refs from Step 1.5 body
The test_merge_pr_skill_fetches_all_pr_files test uses find('Step 3.5')
as the start and find('Step 4') as the end to scope the section under
examination. Mentioning these step numbers in the Step 1.5 prose caused
the section boundary to be detected mid-paragraph (within Step 1.5 itself
rather than at the actual ### Step 3.5 heading), resulting in a false
negative (no 'git diff --name-only' command found in the empty section).
Replaced with prose references: 'PR Changes Inventory section' and
'the conflict report' to avoid polluting the section boundary detection.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(arch): route resolve_log_dir through server.helpers to satisfy REQ-IMP-003
tools_integrations.py was importing autoskillit.execution.session_log directly,
violating the arch rule that tools_*.py may only import from core, pipeline,
and server sub-packages. Re-export resolve_log_dir via server.helpers (an
intra-server module, arch-compliant as L3→L1) and use the module-level import.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add deletion_regression to review-pr finding schema dimension union
The Step 3 JSON schema example in review-pr/SKILL.md had a stale dimension
union string missing deletion_regression. Also adds a targeted test that
checks the schema union string directly, preventing this gap from recurring
(the existing broad test passes because deletion_regression appears in the
7th subagent description but not the schema block).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: Phase 2 ephemeral skill gating and open-kitchen human entry point
Implements all 6 deliverables from issue #269 Phase 2:
1. open-kitchen/close-kitchen SKILL.md files with disable-model-invocation: true
(human-only slash commands, not agent-invocable)
2. Cook session visibility gap fix: mcp.enable(tags={"kitchen"}) in server/__init__.py
when AUTOSKILLIT_KITCHEN_OPEN=1, so cook sessions start with kitchen pre-revealed
3. Platform-aware ephemeral directory resolver: /dev/shm → /tmp → $TMPDIR fallback chain
(resolve_ephemeral_root in workspace/session_skills.py)
4. SkillsDirectoryProvider: tier-aware skill content provider with frontmatter injection
for Tier 2 skills (open-kitchen, close-kitchen get disable-model-invocation: true
in plain sessions, removed in cook sessions)
5. SessionSkillManager: manages per-session ephemeral skill directories, cleans stale
dirs at startup, activate_tier2() removes gate flag on demand
6. Hook enforcement: open_kitchen_guard.py PreToolUse hook blocks open_kitchen from
headless sessions (AUTOSKILLIT_HEADLESS=1 injected by headless.py)
Also adds SkillSessionManager Protocol to core/types.py, wires SessionSkillManager
into ToolContext and _factory.py, registers new hook in hook_registry.py, and adds
16 Phase 2 tests (T1-T16) covering all new components.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: expand requires_decision window in test to cover schema union offset
* chore: commit auto-generated files
* fix(review): address 8 PR review findings from #274
- helpers.py: declare resolve_log_dir in __all__ instead of noqa: F401 backward-compat hack
- tools_integrations.py: guard config.linux_tracing.log_dir against AttributeError
- tools_integrations.py: add exc_info=True to diagnostics read failure warning
- tools_integrations.py: validate session_id against safe char set before path construction
- tools_integrations.py: use .get() for anomalies/proc_trace_tail in _format_diagnostics_section
- tests: replace fragile call_args[0][3] positional access with kwargs.get("body", args[3])
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): quote PR_FILES via --pathspecs-from-file and increase grep context to -B20
- Use `echo "$PR_FILES" | git diff --pathspecs-from-file=-` so space-containing
paths are not word-split by bash
- Increase grep context from -B5 to -B20 when extracting commit SHA from git log -p
output, since diff headers appear more than 5 lines above the matched symbol line
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): fix test boundary detection and anchor deletion_regression search
- Replace find("Step 2") with find("### Step 2") in three tests to prevent
premature truncation of step_15_section when "Step 2" appears in inline prose
("Step 2 / Step 3 as normal") before the actual section header
- Anchor deletion_regression severity test to "deletion_regression — Deliberate"
paragraph instead of first occurrence (which falls in the JSON schema union block),
ensuring the test validates the 7th subagent instruction rather than a template value
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): correct deletion_regression anchor to match markdown bold syntax
The SKILL.md uses **deletion_regression** (markdown bold), so the search
string must be '7. **deletion_regression**' not 'deletion_regression — Deliberate'
(which doesn't appear verbatim in the raw file).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): replace import os as _os alias with plain import os
Unnecessary alias — os is not imported elsewhere in the module and
there is no name collision with other names.
* fix(review): rename SkillSessionManager Protocol to SessionSkillManager
Unifies naming with the concrete implementation class in
workspace/session_skills.py, which was already named SessionSkillManager.
* fix(review): validate session_id and skill_name against path traversal
init_session and activate_tier2 now reject any session_id or skill_name
containing path separators or dot-dot sequences before constructing
paths under the ephemeral root.
* fix(review): replace importlib.reload + vacuous assertion with behavioral test
Uses FastMCP Client to assert GATED_TOOLS are visible after
mcp.enable(tags={'kitchen'}). Eliminates module reload that mutated
global state and could bleed between xdist workers.
* fix(review): replace inspect.getsource() with behavioral test for AUTOSKILLIT_HEADLESS
Calls run_headless_core with a MockSubprocessRunner and asserts
AUTOSKILLIT_HEADLESS=1 appears in the spawned command, replacing
a source-text grep that passed even if the constant was in dead code.
* fix(review): strengthen human-session hook assertion and fix pre-existing E501
test_open_kitchen_guard_allows_human_session now asserts returncode==0
and empty stdout instead of accepting any non-deny response including
silent crashes. Fix pre-existing E501 line-length violations in
test_tools_execution.py that were blocking pre-commit.
* fix(review): rename SessionSkillManager to DefaultSessionSkillManager
Eliminates import ambiguity with the identically-named Protocol in
core/types.py. Updates workspace/__init__.py export, _factory.py
construction, and test imports.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): add path-traversal test for _SAFE_SESSION_ID_RE and split fallback tests
Adds a test asserting None is returned for path-traversal session_id
inputs. Splits the combined no_session_*/crashed_* test into two
focused tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): harden session_skills.py frontmatter handling and session_id validation
- Fix _FM_PATTERN to match empty frontmatter (---\n---) by making the
newline before closing --- optional
- Fix _remove_disable_model_invocation to return bare body when
disable-model-invocation was the only key, avoiding degenerate ---\n\n---
- Add null byte guard to session_id validation in init_session and activate_tier2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): remove resolve_log_dir re-export from helpers.py
resolve_log_dir is an L1 execution symbol; re-exporting it from L3
server/helpers.py was an arch violation. tools_integrations.py now
imports it directly from autoskillit.execution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): strengthen open_kitchen_guard, fix __init__.py comment, remove redundant getattr
- open_kitchen_guard.py: include OSError in exception catch so broken
pipe on stdin.read() fails open instead of propagating uncaught
- server/__init__.py: move 'Must appear after all tool module imports'
comment to just above mcp.disable() where it is factually correct
- tools_integrations.py: access config.linux_tracing.log_dir directly
after the is not None guard; getattr fallback was redundant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(review): remove __all__ re-export of resolve_log_dir from helpers.py
Retains the import in helpers.py (where tools_integrations.py fetches it
within the allowed autoskillit.server namespace per REQ-IMP-003) but
drops the explicit __all__ declaration that advertised it as a public
re-export.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5355a91 commit 2ae4bc8
28 files changed
Lines changed: 1698 additions & 42 deletions
File tree
- src/autoskillit
- core
- execution
- hooks
- pipeline
- server
- skills
- close-kitchen
- merge-pr
- open-kitchen
- review-pr
- write-recipe
- workspace
- tests
- server
- skills
- workspace
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | | - | |
| 137 | + | |
138 | 138 | | |
139 | 139 | | |
| 140 | + | |
140 | 141 | | |
141 | 142 | | |
142 | 143 | | |
| |||
196 | 197 | | |
197 | 198 | | |
198 | 199 | | |
199 | | - | |
| 200 | + | |
| 201 | + | |
200 | 202 | | |
201 | 203 | | |
202 | 204 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
| |||
124 | 125 | | |
125 | 126 | | |
126 | 127 | | |
| 128 | + | |
127 | 129 | | |
128 | 130 | | |
129 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
786 | 786 | | |
787 | 787 | | |
788 | 788 | | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
403 | 403 | | |
404 | 404 | | |
405 | 405 | | |
| 406 | + | |
406 | 407 | | |
407 | 408 | | |
408 | | - | |
| 409 | + | |
| 410 | + | |
409 | 411 | | |
410 | 412 | | |
411 | 413 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
31 | 35 | | |
32 | 36 | | |
33 | 37 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
59 | 61 | | |
60 | 62 | | |
61 | 63 | | |
| |||
75 | 77 | | |
76 | 78 | | |
77 | 79 | | |
| 80 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
49 | 51 | | |
50 | 52 | | |
51 | 53 | | |
| |||
64 | 66 | | |
65 | 67 | | |
66 | 68 | | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
39 | 45 | | |
40 | 46 | | |
41 | 47 | | |
| |||
87 | 93 | | |
88 | 94 | | |
89 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
90 | 101 | | |
91 | 102 | | |
92 | 103 | | |
| |||
102 | 113 | | |
103 | 114 | | |
104 | 115 | | |
| 116 | + | |
105 | 117 | | |
106 | 118 | | |
107 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
73 | 82 | | |
74 | 83 | | |
75 | 84 | | |
| |||
0 commit comments