You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OpenCode's file search reports that the hidden Spec Kit project directory contains no files. Local and open-weight models then miss the constitution, templates, and scripts the Spec Kit commands need. Models that retry by reading a known path directly often continue anyway. OpenCode 1.18.31 and 1.19.3 run that glob through ripgrep without --hidden, so dot-directories are skipped. Re-including the tree on that path takes both !.specify/ and !.specify/** in the project-root .ignore; the contents rule alone still returns no .specify/**/* matches. The OpenCode integration only installed command files and never wrote those exceptions.
OpenCode install and upgrade accept an opt-in --configure-ignore-file flag that appends whichever of !.specify/ and !.specify/** is not already an exact line, keeps existing .ignore bytes as a prefix (including non-ASCII text, CRLF, and a missing final newline), and records the root file as partial ownership. Symlinks, non-files, and unwritable paths are rejected before any write. Uninstall, including with --force, leaves .ignore in place, and installs without the flag, along with other integrations, leave it untouched. Upgrade replays the stored flag, a new --integration-options value replaces the whole stored set, and the integrations reference documents the option and the checked ripgrep behavior.
Tested locally with uv run specify --help
Ran uv run python -m pytest tests/test_agent_config_consistency.py -q locally on macOS for the spec-kit OpencodeIntegration change; it fails the same way on the base branch, so the failure predates this change (it fails the same way on upstream/main).
Ran existing tests with uv sync && uv run pytest uv sync && uv run pytest was not run locally for the spec-kit OpencodeIntegration change either.
Tested with a sample project (if applicable)
No one has checked the spec-kit OpencodeIntegration change with a sample project yet.
Ran uv run python -m pytest tests/test_agent_config_consistency.py -q locally on macOS for the spec-kit OpencodeIntegration change; it fails the same way on the base branch, so the failure predates this change (it fails the same way on upstream/main). Tests for the spec-kit OpencodeIntegration change live in tests/integrations/test_integration_opencode.py.
AI Disclosure
I did not use AI assistance for this contribution
I did use AI assistance (describe below)
AI disclosure
AI was used for assistance.
Extent: AI wrote the code changes and drafted this description.
OpenCode install and upgrade accept an opt-in --configure-ignore-file
flag that appends whichever of !.specify/ and !.specify/** is not
already an exact line, keeps existing .ignore bytes as a prefix
(including non-ASCII text, CRLF, and a missing final newline), and
records the root file as partial ownership. Symlinks, non-files, and
unwritable paths are rejected before any write. Uninstall, including
with --force, leaves .ignore in place, and installs without the flag,
along with other integrations, leave it untouched. Upgrade replays the
stored flag, a new --integration-options value replaces the whole stored
set, and the integrations reference documents the option and the checked
ripgrep behavior.
Fixesgithub#5028
Assisted-by: AI
The flag appends whichever of those two rules is not already an exact line, placing them at the end of the root `.ignore`. Bytes already in the file stay as a prefix, including non-ASCII text, CRLF, and a missing final newline. Default installs leave `.ignore` untouched. The file is recorded with partial ownership. `specify integration uninstall` and `specify integration uninstall --force` both leave it in place, exceptions included. Delete the two lines manually to restore the previous glob behavior.
Deleting rules does not persistently opt out while OpenCode is installed
docs/reference/integrations.md:518
Deleting these lines is not a persistent opt-out while OpenCode remains installed. Partial ownership still hashes the entire .ignore, so any user edit blocks a normal upgrade (manifest.py:340–364, command_upgrade.py:80–87). Adding --force replays the stored flag and restores the rules; it also permits overwriting customized shared scripts and templates. Document the hash-tracking consequence and the safe order: first upgrade with options that omit this flag while preserving other options, then delete the lines. After uninstall, deleting them directly is sufficient.
AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous).
Non-UTF-8 .ignore content aborts install or upgrade
An existing .ignore with a non-UTF-8 comment, such as Latin-1 # café, raises UnicodeDecodeError here and aborts the opted-in install or upgrade. Only ASCII rules need recognition. Use lossless decoding for this membership check and add a non-UTF-8 preservation case; the original bytes can then remain untouched.
AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous).
Non-atomic .ignore writes can destroy existing user rules
record_file() calls Path.write_bytes() (manifest.py:208), which truncates the existing .ignore before writing. A write failure after opening can destroy user rules, and built-in-only installs/upgrades have no lifecycle journal to restore them (_lifecycle.py:468–469). The new disk-full mock raises before opening, so it misses this failure. Use an atomic replacement that preserves permissions, safe-path checks, and lifecycle notifications, and test a failure after output begins.
AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous).
Platform-dependent symlink and permission tests fail unexpectedly
Direct symlink creation can fail on Windows without the required privilege, and the permission-rejection assertions fail under root, which can still read and write these files. Either condition fails this combined test before its remaining cases run. Split the cases so only unsupported symlink and permission checks are skipped, following tests/integrations/test_integration_kimi.py:17–30 and tests/extensions/github/test_github_extension.py:1408–1411. Keep directory and write-failure checks platform-independent.
AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous).
Address the rest of the Copilot review on github#5032. The code fence fix
already landed in b395863; this covers the other four comments:
- Document that upgrades still hash-check .ignore, that --force also
overwrites edited command files, and that the stored flag must be
cleared before removing the two rules.
- Check .ignore (symlink, directory, unreadable, unwritable) before
command files are rendered, and check it again before the write, so
a rejected destination leaves existing command files unchanged.
- Match the two rules as ASCII bytes so a non-UTF-8 .ignore is kept
byte for byte instead of raising UnicodeDecodeError.
- Write .ignore through the journal-aware atomic writer, keeping its
file mode, and record partial ownership afterward, so a failed write
can no longer truncate existing user rules.
Refs github#5028
Bring the branch up to date with main (505781d). github#5034 split
docs/reference/integrations.md into per-agent guides under
docs/integrations/ and deleted the old page, which conflicted with this
branch's edits to it.
Resolution: accept the deletion and move this branch's "OpenCode:
hidden Spec Kit files" section into docs/integrations/opencode.md as
"Hidden Spec Kit Files", and list it in the Integration-Specific
Options table in docs/integrations/cli.md, which is where main now
points readers for agent-specific options. The old catalog table rows
and options table row are dropped with the deleted page.
Addressed the Copilot review: the .ignore section now documents that upgrades still hash-check the file, that --force also overwrites edited command files, and that the stored flag must be cleared before removing the rules. .ignore is checked before command files are rendered and again before the write, the two rules are matched as bytes so a non-UTF-8 file is kept as-is, and the write goes through the journal-aware atomic writer with the file mode kept. Also merged main; since #5034 moved agent docs, the OpenCode section now lives in docs/integrations/opencode.md. ruff, markdownlint and the full pytest suite pass locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
triage-must-haveVerdict: high-value, important work for Spec Kit — do first
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
OpenCode's file search reports that the hidden Spec Kit project directory contains no files. Local and open-weight models then miss the constitution, templates, and scripts the Spec Kit commands need. Models that retry by reading a known path directly often continue anyway. OpenCode 1.18.31 and 1.19.3 run that glob through ripgrep without --hidden, so dot-directories are skipped. Re-including the tree on that path takes both !.specify/ and !.specify/** in the project-root .ignore; the contents rule alone still returns no .specify/**/* matches. The OpenCode integration only installed command files and never wrote those exceptions.
OpenCode install and upgrade accept an opt-in --configure-ignore-file flag that appends whichever of !.specify/ and !.specify/** is not already an exact line, keeps existing .ignore bytes as a prefix (including non-ASCII text, CRLF, and a missing final newline), and records the root file as partial ownership. Symlinks, non-files, and unwritable paths are rejected before any write. Uninstall, including with --force, leaves .ignore in place, and installs without the flag, along with other integrations, leave it untouched. Upgrade replays the stored flag, a new --integration-options value replaces the whole stored set, and the integrations reference documents the option and the checked ripgrep behavior.
Fixes #5028
Testing
uv run specify --helpRan
uv run python -m pytest tests/test_agent_config_consistency.py -qlocally on macOS for the spec-kit OpencodeIntegration change; it fails the same way on the base branch, so the failure predates this change (it fails the same way on upstream/main).uv sync && uv run pytestuv sync && uv run pytestwas not run locally for the spec-kit OpencodeIntegration change either.No one has checked the spec-kit OpencodeIntegration change with a sample project yet.
Ran
uv run python -m pytest tests/test_agent_config_consistency.py -qlocally on macOS for the spec-kit OpencodeIntegration change; it fails the same way on the base branch, so the failure predates this change (it fails the same way on upstream/main). Tests for the spec-kit OpencodeIntegration change live intests/integrations/test_integration_opencode.py.AI Disclosure
AI disclosure
AI was used for assistance.