* feat(cli,domain): support non-global namespace skill download
Parse namespace from skill name using -- separator (e.g.,
astroclaw--api-gateway) so users don't need --namespace flag.
Allow anonymous download for any PUBLIC skill regardless of namespace.
CLI changes:
- Add cli/src/shared/skill-name-parser.ts utility
- Update install and remove commands to parse skill name argument
- 10 unit tests covering edge cases
Domain changes:
- SkillDownloadService.isAnonymousDownloadAllowed: drop namespace
type check, only require PUBLIC visibility
- Update test to expect success for team-namespace public skill
Synced from SAAS commit 26c67e31b1221249cf9b73321d1b726d8ba6e6df
* fix(cli): use bun:test instead of vitest in skill-name-parser test
Covers the new "access denied — token may lack required scope" error
path with a fake-registry 'forbidden' failure mode. Prevents the
improved 403 message from regressing silently.
- Fix test fixture: warnings-only response now uses valid=false to
match real backend behavior (warnings make dry-run invalid)
- Distinguish 403 from 401 in CLI error messages: 403 now says
"access denied — token may lack required scope" with a hint to
regenerate the token, rather than the generic "authentication failed"
Fix three blockers and one contract drift issue surfaced in code review:
1. API token policy: add skill:publish scope policy and authentication
policy for /api/cli/v1/skills/*/publish/validate. Without these the
AntPathMatcher pattern /publish would not cover /publish/validate,
so Bearer-token requests would be rejected by the scope filter.
2. Warnings semantics: dry-run now treats warnings as making valid=false.
The CLI publish flow uses confirmWarnings=false, so the real publish
rejects any warnings; dry-run must mirror that to avoid false positives.
3. Visibility parameter: validate endpoint now accepts the same
visibility multipart field as publish. The CLI forwards --visibility
so invalid values are caught at dry-run time rather than at publish.
4. Schema drift: resolvedSlug and resolvedVersion are nullable in
practice (returned as null when validation fails before resolution).
Updated schema.d.ts to reflect string | null instead of optional string.
Tests added:
- RouteSecurityPolicyRegistryTest: validate endpoint scope check
- CliDryRunValidateTest: custom + invalid visibility cases
- publish-dry-run.test.ts: --visibility forwarded to server
- Exit non-zero (code 6) when --dry-run validation fails, enabling
CI/CD pipeline integration
- Add archived skill check: dry-run now detects when the publisher's
own skill is archived
- Add version-exists check: dry-run now detects when the resolved
version is already published
- Use StandardCharsets.UTF_8 for SKILL.md content parsing
Add a validate-only endpoint (POST /api/cli/v1/skills/{namespace}/publish/validate)
that runs the full pre-publish validation chain without persisting anything.
This allows developers to check their package locally before actual publishing.
The validation covers:
- SKILL.md existence and frontmatter parsing (name, description required)
- File extension whitelist and size limits
- Credential leak scanning with line-number precision
- Slug generation and name conflict detection
CLI usage: `skillhub publish <path> --dry-run`
Closes#429
When --agent is provided without --scope, scope was inferred via
root.startsWith(cwd), which mislabels user roots as project when
cwd === home. Use profile.userRoots(home) membership instead, so the
candidate scope reflects the profile's intent rather than path prefix
overlap. The chosen root path itself is unchanged.
- Distinguish user vs project install scope via explicit --scope flag
- Interactive mode prompts for scope when --scope/--agent/--dir not provided
- Non-interactive bare install preserves existing behavior (backward compatible)
- Mutual exclusion: --dir cannot be combined with --scope or --agent
- Symmetric fallback: --scope user falls back to ~/.agents/skills,
--scope project falls back to <cwd>/.agents/skills
- Strict TTY check requires both stdin and stdout TTY plus no --json
- Scope-aware candidate generation avoids root.startsWith(cwd) misjudgement
when cwd === home or paths overlap
- Correct gemini-cli (.gemini/skills) and kiro-cli (.kiro/skills) paths
in install path tables across README and guide docs
- Note CLI fallback uses .agents/skills (with s) in skill protocol doc
Windows ZIP library produces backslashes in file paths while Unix uses forward slashes. Normalize all paths to forward slashes before assertion to ensure tests pass on all platforms.
- Fix Windows test failure by using regex that accepts both / and \ path separators in install-command.test.ts
- Rename contradictory test case in publish-command.test.ts from "surfaces a non-zero exit" to "is handled without crash" to match actual assertion behavior
Migrated 39 test files covering CLI integration and unit testing:
- 6 new integration tests (auth-resolution, concurrency, cross-command, inventory-resilience, multi-registry, version-upgrade-flow)
- Enhanced 7 existing integration tests with comprehensive scenarios
- Updated 2 unit tests with correct exit code expectations
All tests use fake registry approach (no E2E/browser required) and pass lint/build/test checks.
- Handle 502/503 status codes as network errors (EXIT.network = 3)
- Previously these were treated as generic errors (EXIT.generic = 1)
- Fixes integration tests for login and search network failure scenarios
- Bump version to 0.1.4
- Add integration tests for doctor, install, list, publish, remove, whoami commands
- Expand fake-registry with resolve/delete state capture for real assertions
- Fix update command: use correct package name @astron-team/skillhub from constants
- Refactor runUpdateCommand to accept string[] instead of fragile string splitting
- Add dependency injection to updateCommand for testable unit tests without global mocks
- Replace package.json import with codegen (scripts/generate-pkg-info.ts) to avoid
leaking devDependencies into the build artifact
- Fix startNetworkFailureServer TOCTOU race by keeping listener alive
- Add TODO markers for known help command bugs (--json not forwarded, unknown topic crash)
- Extend update integration test timeout for real npm registry checks
The issue was that new URL().pathname returns Unix-style paths on Windows
(e.g., /D:/a/skillhub/...) which Bun.spawn() cannot resolve correctly.
Using fileURLToPath() converts the URL to a proper platform-specific path.
Changes:
- cli/test/helpers/run-cli.ts: use fileURLToPath for cwd
- cli/test/integration/version-command.test.ts: same fix for build spawn
Bun.which('bun') on Windows CI returns a non-existent path
(C:\Users\runneradmin\.bun\bin\bun.exe), causing all integration
tests to fail. Add existsSync() check to fallback to process.execPath
when the resolved path doesn't exist.
Also fix version-command.test.ts to use process.execPath instead of
hardcoded 'bun' string for cross-platform compatibility.
Fixes 19 failing integration tests on Windows platform.
- Use Bun.which() with process.execPath fallback in run-cli helper to
resolve bun executable on Windows (fixes 22 integration tests)
- Normalize paths in credentials-store test for Windows backslash compat
- Use shell: true on Windows in updater spawn for proper exe resolution
Replace 'any' type annotation with proper type guard in inventory-store.ts
and add optional chaining in test to satisfy TypeScript strict checks.
All three platforms (Ubuntu, macOS, Windows) CI checks now pass.
Add 36 test cases covering:
- Path traversal and symlink attack prevention in archive extraction
- SkillHubClient error handling (401/403/404/network) for all endpoints
- Inventory store concurrent writes and stale lock recovery
- Config store read/write round-trip
- Platform utilities (package-manager, updater, paths)
- Output formatting (printResult, humanize)
Tests use cross-platform commands (node) instead of shell builtins
for CI compatibility across macOS/Linux/Windows.
Protect doctor metadata scanning from symlinked agent, skill, and .skillhub directories, and make inventory mutations use locked atomic writes with stale lock recovery.