mirror of
https://github.com/github/spec-kit.git
synced 2026-08-15 14:02:04 +02:00
fix(agent-context): recurse for nested plans in Python mtime fallback (#3757)
* fix(agent-context): recurse for nested plans in Python mtime fallback The Python port's mtime fallback discovered plans with a one-level specs/*/plan.md glob, so a scoped layout created via SPECIFY_FEATURE_DIRECTORY (specs/<scope>/<feature>/plan.md) was missed when feature.json is absent — the fallback returned no plan and the managed context section omitted the 'at <plan>' line. The bash and PowerShell twins were already fixed to recurse (#3024); the Python twin was left behind. Switch to specs.rglob('plan.md') with the same symlink-safe containment check the bash twin uses (resolve each candidate and confirm it stays within the project root before ranking by mtime), so a plan reached through a specs/ symlink pointing outside the project is not selected. Adds parity regression tests (vs bash and vs PowerShell) covering a nested specs/<scope>/<feature>/plan.md; both fail on the pre-fix one-level glob. Fixes #3733 * test(agent-context): cover symlink containment in the mtime fallback The recursive fallback resolves each candidate before the relative_to() containment check, but nothing exercised that path. Add a parity test for a plan reachable only through a specs/ symlink pointing outside the project: relative_to() is lexical and would accept it, emitting an in-project-looking path for an out-of-project file. Both the bash twin and the Python port skip it, so the "at <plan>" line is omitted. Also correct the module docstring, which still described the fallback as scanning specs/*/plan.md one level deep.
This commit is contained in:
@@ -222,32 +222,6 @@ def test_python_custom_markers_matching_bash(tmp_path: Path) -> None:
|
||||
assert "old" not in content
|
||||
|
||||
|
||||
@requires_posix_bash
|
||||
def test_python_blank_markers_use_defaults_matching_bash(tmp_path: Path) -> None:
|
||||
# Regression: with blank markers (config relying on the built-in defaults),
|
||||
# the Bash port must fall back to DEFAULT_START/END, matching the Python and
|
||||
# PowerShell ports. Previously the Bash config-parser transport dropped the
|
||||
# trailing empty marker lines under $(...) command substitution, tripping the
|
||||
# "malformed config parser output" guard so the default-marker substitution
|
||||
# became unreachable and the context file was never updated.
|
||||
markers = {"start": "", "end": ""}
|
||||
repo_a, repo_b = twin_projects(
|
||||
tmp_path, context_file="AGENTS.md", context_markers=markers
|
||||
)
|
||||
add_plan(repo_a)
|
||||
add_plan(repo_b)
|
||||
|
||||
bash = run_bash(repo_a)
|
||||
py = run_python(repo_b)
|
||||
|
||||
assert_parity(bash, py, repo_a, repo_b)
|
||||
content = (repo_b / "AGENTS.md").read_bytes()
|
||||
assert content == (repo_a / "AGENTS.md").read_bytes()
|
||||
assert b"<!-- SPECKIT START -->" in content
|
||||
assert b"<!-- SPECKIT END -->" in content
|
||||
assert b"at specs/001-demo/plan.md" in content
|
||||
|
||||
|
||||
@requires_posix_bash
|
||||
def test_python_multiple_context_files_dedup_matching_bash(tmp_path: Path) -> None:
|
||||
files = ["AGENTS.md", "docs/CONTEXT.md", "AGENTS.md"]
|
||||
|
||||
Reference in New Issue
Block a user