* fix: prevent ambiguous TOML closing quotes when body ends with `"` (#2113)
_render_toml_string placed the closing `"""` inline with content, so
a body ending with `"` produced `""""` (four consecutive quotes).
While technically valid TOML 1.0, this breaks stricter parsers such as
Gemini CLI v0.27.2.
Insert a newline before the closing delimiter when the body ends with a
quote character. Same treatment for the single-quote (`'''`) fallback.
Adds both a positive test (body ending with `"` must not produce
`""""`) and a negative test (safe bodies keep the inline delimiter).
* fix: use line-ending backslash instead of newline for TOML closing delimiters
Address PR review feedback:
- Replace sep=newline with TOML line-ending backslash so the parsed
value does not gain a trailing newline when body ends with a quote.
- For literal string (''') fallback, skip to escaped basic string when
value ends with single quote instead of inserting a newline.
- Make test body multiline so it exercises the """ rendering path,
and assert no trailing newline in parsed value.
* test: cover escaped basic-string fallback when body has triple-quotes and ends with single-quote
Addresses review feedback from PR #2115: adds test for the branch
where the body contains '"""' and ends with "'", which forces
_render_toml_string() through the escaped basic-string fallback
instead of the '''...''' literal-string path (since '''' would
produce the same ambiguous-closing-delimiter problem).
* Stage 6: Complete migration — remove legacy scaffold path (#1924)
Remove the legacy GitHub download and offline scaffold code paths.
All 26 agents now use the integration system exclusively.
Code removal (~1073 lines from __init__.py):
- download_template_from_github(), download_and_extract_template()
- scaffold_from_core_pack(), _locate_release_script()
- install_ai_skills(), _get_skills_dir (restored slim version for presets)
- _has_bundled_skills(), _migrate_legacy_kimi_dotted_skills()
- AGENT_SKILLS_MIGRATIONS, _handle_agent_skills_migration()
- _parse_rate_limit_headers(), _format_rate_limit_error()
- Three-way branch in init() collapsed to integration-only
Config derivation (single source of truth):
- AGENT_CONFIG derived from INTEGRATION_REGISTRY (replaced 180-line dict)
- CommandRegistrar.AGENT_CONFIGS derived from INTEGRATION_REGISTRY (replaced 160-line dict)
- Backward-compat constants kept for presets/extensions: SKILL_DESCRIPTIONS,
NATIVE_SKILLS_AGENTS, DEFAULT_SKILLS_DIR
Release pipeline cleanup:
- Deleted create-release-packages.sh/.ps1 (948 lines of ZIP packaging)
- Deleted create-github-release.sh, generate-release-notes.sh
- Deleted simulate-release.sh, get-next-version.sh, update-version.sh
- Removed .github/workflows/scripts/ directory entirely
- release.yml is now self-contained: check, notes, release all inlined
- Install instructions use uv tool install with version tag
Test cleanup:
- Deleted test_ai_skills.py (tested removed functions)
- Deleted test_core_pack_scaffold.py (tested removed scaffold)
- Cleaned test_agent_config_consistency.py (removed 19 release-script tests)
- Fixed test_branch_numbering.py (removed dead monkeypatches)
- Updated auto-promote tests (verify files created, not tip messages)
1089 tests pass, 0 failures, ruff clean.
* fix: resolve merge conflicts with #2051 (claude as skills)
- Fix circular import: move CommandRegistrar import in claude
integration to inside method bodies (was at module level)
- Lazy-populate AGENT_CONFIGS via _ensure_configs() to avoid
circular import at class definition time
- Set claude registrar_config to .claude/commands (extension/preset
target) since the integration handles .claude/skills in setup()
- Update tests from #2051 to match: registrar_config assertions,
remove --integration tip assertions, remove install_ai_skills mocks
1086 tests pass.
* fix: properly preserve claude skills migration from #2051
Restore ClaudeIntegration.registrar_config to .claude/skills (not
.claude/commands) so extension/preset registrations write to the
correct skills directory.
Update tests that simulate claude setup to use .claude/skills and
check for SKILL.md layout. Some tests still need updating for the
full skills path — 10 remaining failures from the #2051 test
expectations around the extension/preset skill registration flow.
WIP: 1076/1086 pass.
* fix: properly handle SKILL.md paths in extension update rollback and tests
Fix extension update rollback using _compute_output_name() for SKILL.md
agents (converts dots to hyphens in skill directory names). Previously
the backup and cleanup code constructed paths with raw command names
(e.g. speckit.test-ext.hello/SKILL.md) instead of the correct computed
names (speckit-test-ext-hello/SKILL.md).
Test fixes for claude skills migration:
- Update claude tests to use .claude/skills paths and SKILL.md layout
- Use qwen (not claude) for skills-guard tests since claude's agent dir
IS the skills dir — creating it triggers command registration
- Fix test_extension_command_registered_when_extension_present to check
skills path format
1086 tests pass, 0 failures, ruff clean.
* fix: address PR review — lazy init, assertions, deprecated flags
- _ensure_configs(): catch ImportError (not Exception), don't set
_configs_loaded on failure so retries work
- Move _ensure_configs() before unregister loop (not inside it)
- Module-level try/except catches ImportError specifically
- Remove tautology assertion (or True) in test_extensions.py
- Strengthen preset provenance assertion to check source: field
- Mark --offline, --skip-tls, --debug, --github-token as hidden
deprecated no-ops in init()
1086 tests pass.
* fix: remove deleted release scripts from pyproject.toml force-include
Removes force-include entries for create-release-packages.sh/.ps1
which were deleted but still referenced in [tool.hatch.build].