Skip to content

feat(extensions): port update-agent-context to Python#3387

Open
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:feat/3281-port-agent-context
Open

feat(extensions): port update-agent-context to Python#3387
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:feat/3281-port-agent-context

Conversation

@marcelsafin

Copy link
Copy Markdown
Contributor

Description

Ports the agent-context extension updater to Python, per #3281. Follows the pattern from the check-prerequisites PoC (#3302): additive port, no changes to the bash or PowerShell scripts, parity tests that run both implementations side by side.

The bash version already ran its core logic through embedded Python heredocs, so this port mostly lifts that logic into a standalone script:

  • extensions/agent-context/scripts/python/update_agent_context.py — config parsing (context_files/context_file/markers), self-seeding from init-options.json via agent-context-defaults.json, path validation (absolute/backslash/../escape rejection), plan-path resolution (feature.json first, mtime fallback), marker upsert for all four cases (both markers, start only, end only, none), CRLF normalization, and .mdc frontmatter repair (alwaysApply: true).
  • Soft gates preserved: missing config, missing PyYAML, and unparseable config all exit 0 with a message on stderr, matching the bash behavior.
  • tests/extensions/test_update_agent_context_python_parity.py — 22 parity tests. Bash tests compare exit code, normalized stdout/stderr, and resulting context-file bytes. PowerShell tests compare resulting file content and skip when pwsh is unavailable.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest (3790 passed, 107 skipped)
  • Parity suite: 20 passed locally, 2 PowerShell tests skipped (no pwsh on this machine; they run in CI)

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Ported and tested with GitHub Copilot CLI. I reviewed the diff and verified parity behavior manually.

Fixes #3281

Ports the agent-context extension updater to a single Python script,
per github#3281 and the check-prerequisites PoC pattern from github#3302. The bash
version already ran its core logic through embedded Python heredocs, so
the port lifts that logic into a standalone script. Parity tests run
bash and Python side by side and compare output and resulting
context-file bytes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 7, 2026 00:03
@marcelsafin marcelsafin requested a review from mnriem as a code owner July 7, 2026 00:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Ports the agent-context extension’s context-file updater to a standalone Python script, alongside a new parity test suite to ensure behavior matches the existing Bash/PowerShell implementations.

Changes:

  • Add extensions/agent-context/scripts/python/update_agent_context.py implementing the updater logic in Python.
  • Add tests/extensions/test_update_agent_context_python_parity.py to run Bash vs Python (and some PowerShell vs Python) parity checks.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
extensions/agent-context/scripts/python/update_agent_context.py New Python implementation of the agent-context updater (config parsing, plan resolution, section upsert, .mdc frontmatter repair).
tests/extensions/test_update_agent_context_python_parity.py New parity test suite comparing Python behavior/output with Bash and PowerShell variants.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +50
def _collect_context_files(data: dict, project_root: str) -> list[str]:
"""Resolve the managed context files from config, mirroring the bash logic."""
context_files: list[str] = []
seen: set[str] = set()
case_insensitive = sys.platform.startswith(("win32", "cygwin"))

def add(value: object) -> None:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3c105c7: added msys to the platform tuple, matching the uname gate in the bash script.

Comment on lines +444 to +461
@pytest.mark.skipif(not POWERSHELL, reason="no PowerShell available")
def test_python_upsert_matches_powershell(tmp_path: Path) -> None:
repo_a = make_project(tmp_path / "proj-ps", context_file="AGENTS.md")
repo_b = make_project(tmp_path / "proj-py", context_file="AGENTS.md")
existing = (
"# My project\n\n"
"<!-- SPECKIT START -->\nstale\n<!-- SPECKIT END -->\n"
"\ntail\n"
)
for repo in (repo_a, repo_b):
add_plan(repo)
(repo / "AGENTS.md").write_text(existing, encoding="utf-8")

ps = run_powershell(repo_a)
py = run_python(repo_b)

assert ps.returncode == py.returncode == 0, ps.stderr + py.stderr
assert (repo_a / "AGENTS.md").read_bytes() == (repo_b / "AGENTS.md").read_bytes()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added in 3c105c7: test_python_unparseable_config_matching_bash locks in exit 0 plus the stderr messages for invalid YAML.

…ble config gate

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Low

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.

Port agent-context extension scripts to Python

3 participants