gemiterm 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -9
- package/package.json +13 -4
- package/src/cli/command-registry.ts +66 -62
- package/src/cli/commands/continue-command.ts +75 -1
- package/src/cli/commands/install-skills-command.ts +35 -0
- package/src/cli/commands/new-command.ts +62 -0
- package/src/cli/index.ts +19 -44
- package/src/cli/utils/long-arg-guard.ts +28 -0
- package/src/cli/utils/prompt-file.ts +26 -0
- package/src/infrastructure/cli-parser.ts +77 -0
- package/src/infrastructure/io.ts +9 -0
- package/src/services/skills-cli-driver.ts +58 -0
- package/src/services/skills-service.ts +52 -0
- package/.env +0 -2
- package/.github/workflows/manual-release.yml +0 -34
- package/.github/workflows/release.yml +0 -198
- package/.github/workflows/test.yml +0 -29
- package/.opencode/commands/opsx-apply.md +0 -152
- package/.opencode/commands/opsx-archive.md +0 -157
- package/.opencode/commands/opsx-explore.md +0 -169
- package/.opencode/commands/opsx-propose.md +0 -104
- package/.opencode/commands/opsx-sync.md +0 -140
- package/.opencode/commands/search-intelligently.md +0 -9
- package/.opencode/opencode.json +0 -20
- package/.opencode/skills/intellisearch/.version +0 -1
- package/.opencode/skills/intellisearch/SKILL.md +0 -84
- package/.opencode/skills/intellisearch/references/brave-search.md +0 -67
- package/.opencode/skills/intellisearch/references/ddg-search.md +0 -79
- package/.opencode/skills/intellisearch/references/deepwiki-tools.md +0 -246
- package/.opencode/skills/intellisearch/references/examples.md +0 -97
- package/.opencode/skills/intellisearch/references/gh-cli.md +0 -143
- package/.opencode/skills/intellisearch/references/google-search.md +0 -40
- package/.opencode/skills/intellisearch/references/search-workflow.md +0 -143
- package/.opencode/skills/intellisearch/references/workflow.md +0 -115
- package/.opencode/skills/openspec-apply-change/SKILL.md +0 -159
- package/.opencode/skills/openspec-archive-change/SKILL.md +0 -117
- package/.opencode/skills/openspec-explore/SKILL.md +0 -287
- package/.opencode/skills/openspec-propose/SKILL.md +0 -111
- package/.opencode/skills/openspec-sync-specs/SKILL.md +0 -147
- package/.serena/project.yml +0 -133
- package/AGENTS.md +0 -136
- package/CHANGELOG.md +0 -3
- package/bun.lock +0 -105
- package/docs/INSTALL.md +0 -185
- package/docs/PLAYWRIGHT_CLI_API.md +0 -306
- package/docs/python-release-for-reference.md +0 -175
- package/examples/sample_json_export.json +0 -32
- package/examples/sample_markdown_export.md +0 -221
- package/examples/usage_examples.sh +0 -222
- package/install.ps1 +0 -264
- package/install.sh +0 -275
- package/openspec/MAESTRO_MIGRATION.md +0 -180
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/design.md +0 -194
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/proposal.md +0 -52
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/specs/multi-profile-conversations/spec.md +0 -133
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/tasks.md +0 -95
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/design.md +0 -28
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/proposal.md +0 -22
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/specs/interactive-prompt-loop/spec.md +0 -35
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/tasks.md +0 -28
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/design.md +0 -323
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/proposal.md +0 -122
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/specs/no-capability-changes/spec.md +0 -29
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/tasks.md +0 -172
- package/openspec/changes/archive/2026-06-09-v2-install-migration/.openspec.yaml +0 -2
- package/openspec/changes/archive/2026-06-09-v2-install-migration/design.md +0 -241
- package/openspec/changes/archive/2026-06-09-v2-install-migration/proposal.md +0 -41
- package/openspec/changes/archive/2026-06-09-v2-install-migration/specs/v2-installer/spec.md +0 -205
- package/openspec/changes/archive/2026-06-09-v2-install-migration/tasks.md +0 -97
- package/openspec/changes/commander-cli-parser/.openspec.yaml +0 -2
- package/openspec/changes/commander-cli-parser/design.md +0 -107
- package/openspec/changes/commander-cli-parser/proposal.md +0 -31
- package/openspec/changes/commander-cli-parser/specs/cli/spec.md +0 -48
- package/openspec/changes/commander-cli-parser/tasks.md +0 -33
- package/openspec/changes/cross-platform-build-and-ci/.openspec.yaml +0 -2
- package/openspec/changes/cross-platform-build-and-ci/design.md +0 -213
- package/openspec/changes/cross-platform-build-and-ci/proposal.md +0 -50
- package/openspec/changes/cross-platform-build-and-ci/specs/path-and-file-mediation/spec.md +0 -335
- package/openspec/changes/cross-platform-build-and-ci/specs/release-pipeline/spec.md +0 -95
- package/openspec/changes/cross-platform-build-and-ci/tasks.md +0 -164
- package/openspec/config.yaml +0 -20
- package/openspec/specs/auth/spec.md +0 -394
- package/openspec/specs/cli/spec.md +0 -108
- package/openspec/specs/commands/spec.md +0 -409
- package/openspec/specs/configuration/spec.md +0 -130
- package/openspec/specs/conversations/spec.md +0 -139
- package/openspec/specs/domain-model/spec.md +0 -128
- package/openspec/specs/formatters/spec.md +0 -158
- package/openspec/specs/install-browser/spec.md +0 -146
- package/openspec/specs/interactive-prompt-loop/spec.md +0 -41
- package/openspec/specs/logger/spec.md +0 -71
- package/openspec/specs/mediator/spec.md +0 -72
- package/openspec/specs/multi-profile-conversations/spec.md +0 -145
- package/openspec/specs/path-utils/spec.md +0 -101
- package/openspec/specs/profiles/spec.md +0 -94
- package/openspec/specs/storage/spec.md +0 -198
- package/openspec/specs/testing/spec.md +0 -237
- package/openspec/specs/v2-installer/spec.md +0 -205
- package/openspec/specs/validators/spec.md +0 -65
- package/scripts/build.ts +0 -88
- package/scripts/clean-build.ps1 +0 -4
- package/scripts/clean-build.sh +0 -5
- package/scripts/install-browser.ps1 +0 -5
- package/scripts/install-browser.sh +0 -6
- package/scripts/lint-path-mediation.ps1 +0 -65
- package/scripts/lint-path-mediation.sh +0 -40
- package/tests/cli/auth-command.test.ts +0 -220
- package/tests/cli/command-registry.test.ts +0 -67
- package/tests/cli/continue-command.test.ts +0 -100
- package/tests/cli/delete-command.test.ts +0 -128
- package/tests/cli/export-all-command.test.ts +0 -375
- package/tests/cli/install-browser-command.test.ts +0 -48
- package/tests/cli/list-command.test.ts +0 -179
- package/tests/cli/new-command.test.ts +0 -139
- package/tests/cli/status-command.test.ts +0 -106
- package/tests/core/query-handlers.test.ts +0 -187
- package/tests/fixtures/auth-fixtures.ts +0 -98
- package/tests/fixtures/chat-fixtures.ts +0 -87
- package/tests/infrastructure/cli-table.test.ts +0 -107
- package/tests/infrastructure/formatters.test.ts +0 -202
- package/tests/infrastructure/io.test.ts +0 -197
- package/tests/infrastructure/logger.test.ts +0 -74
- package/tests/infrastructure/storage.test.ts +0 -335
- package/tests/infrastructure/validators.test.ts +0 -67
- package/tests/integration/commands/auth.test.ts +0 -186
- package/tests/integration/commands/continue.test.ts +0 -130
- package/tests/integration/commands/delete.test.ts +0 -140
- package/tests/integration/commands/export.test.ts +0 -266
- package/tests/integration/commands/fetch.test.ts +0 -238
- package/tests/integration/commands/list.test.ts +0 -281
- package/tests/integration/commands/profile.test.ts +0 -258
- package/tests/integration/commands/status.test.ts +0 -223
- package/tests/integration/installer-script-shape.test.ts +0 -67
- package/tests/parity/compare-outputs.ts +0 -359
- package/tests/parity/test-commands-parity.ps1 +0 -82
- package/tests/parity/test-commands-parity.sh +0 -61
- package/tests/services/auth-service.test.ts +0 -315
- package/tests/services/cookie-monitor.test.ts +0 -229
- package/tests/services/cookie-storage-service.test.ts +0 -230
- package/tests/services/gemini-client-wrapper.test.ts +0 -688
- package/tests/services/install-browser-service.test.ts +0 -83
- package/tests/services/playwright-cli-driver.test.ts +0 -468
- package/tests/services/profile-auth-manager.test.ts +0 -334
- package/tests/services/profile-service.test.ts +0 -224
- package/tests/setup.ts +0 -95
- package/tests/smoke/smoke.test.ts +0 -52
- package/tests/unit/config.test.ts +0 -159
- package/tests/unit/errors.test.ts +0 -119
- package/tests/unit/formatters.test.ts +0 -316
- package/tests/unit/mediator.test.ts +0 -152
- package/tests/unit/path-utils.test.ts +0 -289
- package/tsconfig.json +0 -16
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
## ADDED Requirements
|
|
2
|
-
|
|
3
|
-
### Requirement: CI Test Runs On Pull Requests And Pushes To Main
|
|
4
|
-
The system MUST run a test job on every `pull_request` event and every `push` to the `main` branch. The test job MUST run on `ubuntu-latest` and MUST execute `bun install --frozen-lockfile`, `bun test`, `bun run typecheck`, and a path-and-file mediation lint check in that order. A failure in any of these commands MUST cause the test job to exit non-zero and fail the workflow.
|
|
5
|
-
|
|
6
|
-
#### Scenario: Pull request to main runs the test job
|
|
7
|
-
- **WHEN** a contributor opens a pull request targeting `main`
|
|
8
|
-
- **THEN** the `test` workflow runs on `ubuntu-latest`, executes `bun install --frozen-lockfile`, `bun test`, `bun run typecheck`, and the path-and-file mediation lint check, and the pull request cannot be merged while the test job is failing
|
|
9
|
-
|
|
10
|
-
#### Scenario: Push to main runs the test job
|
|
11
|
-
- **WHEN** commits are pushed directly to the `main` branch
|
|
12
|
-
- **THEN** the `test` workflow runs the same commands on `ubuntu-latest` and reports success or failure based on their exit codes
|
|
13
|
-
|
|
14
|
-
#### Scenario: Test failure fails CI
|
|
15
|
-
- **WHEN** `bun test` exits with a non-zero status (one or more test cases fail)
|
|
16
|
-
- **THEN** the test job exits non-zero and the workflow is marked as failed
|
|
17
|
-
|
|
18
|
-
#### Scenario: Typecheck failure fails CI
|
|
19
|
-
- **WHEN** `bun run typecheck` exits with a non-zero status (TypeScript reports one or more errors)
|
|
20
|
-
- **THEN** the test job exits non-zero and the workflow is marked as failed
|
|
21
|
-
|
|
22
|
-
#### Scenario: Path-and-file mediation lint failure fails CI
|
|
23
|
-
- **WHEN** the lint check finds a `node:fs`, `node:path`, or `node:os` import in `src/` outside the allowed exemptions (see the `path-and-file-mediation` spec)
|
|
24
|
-
- **THEN** the test job exits non-zero and the workflow is marked as failed
|
|
25
|
-
|
|
26
|
-
### Requirement: Cross-Platform Build On Version Tags
|
|
27
|
-
The system MUST run a cross-platform build matrix whenever a tag matching the pattern `v*` is pushed, and MUST also run on `workflow_dispatch` for manual builds. The build matrix MUST include at least three jobs: `build-linux` on `ubuntu-latest`, `build-windows` on `windows-latest`, and `build-wsl` on `ubuntu-latest` producing a Linux x64 binary suitable for WSL. Each job MUST verify the build artifact exists, report its size, and upload it via `actions/upload-artifact@v4`.
|
|
28
|
-
|
|
29
|
-
#### Scenario: Tag push triggers the build matrix
|
|
30
|
-
- **WHEN** a tag matching `v*` (for example `v2.0.0`) is pushed to the repository
|
|
31
|
-
- **THEN** the build workflow runs the `build-linux`, `build-windows`, and `build-wsl` jobs in parallel, each verifies its artifact, and each uploads the artifact via `actions/upload-artifact@v4`
|
|
32
|
-
|
|
33
|
-
#### Scenario: Manual workflow dispatch accepts a custom tag
|
|
34
|
-
- **WHEN** a maintainer triggers the build workflow via `workflow_dispatch` and supplies a `tag` input (for example `v2.0.1-rc.1`)
|
|
35
|
-
- **THEN** the build jobs use the supplied tag value to name the output binary (for example `gemiterm-v2.0.1-rc.1`) instead of the event ref name
|
|
36
|
-
|
|
37
|
-
#### Scenario: Missing build artifact fails the job
|
|
38
|
-
- **WHEN** a build job completes but the expected binary file (for example `dist/GemiTerm` or `dist/GemiTerm.exe`) does not exist
|
|
39
|
-
- **THEN** the build job exits non-zero and the workflow is marked as failed
|
|
40
|
-
|
|
41
|
-
### Requirement: GitHub Release Published On Version Tags
|
|
42
|
-
The system MUST publish a GitHub Release whenever a tag matching the pattern `v*` is pushed. The release job MUST depend on (chain after) both the test and build jobs. The release MUST use `softprops/action-gh-release@v2` with auto-generated release notes, and MUST attach the `GemiTerm` (Linux) binary, the `GemiTerm.exe` (Windows) binary, the `install.sh` script, and the `install.ps1` script as release assets.
|
|
43
|
-
|
|
44
|
-
#### Scenario: Tag push creates a GitHub release with all artifacts
|
|
45
|
-
- **WHEN** a tag matching `v*` (for example `v2.0.0`) is pushed
|
|
46
|
-
- **THEN** the test and build jobs run first, and on success the release job creates a GitHub Release named after the tag, with auto-generated release notes, attaching `GemiTerm`, `GemiTerm.exe`, `install.sh`, and `install.ps1` as release assets
|
|
47
|
-
|
|
48
|
-
#### Scenario: Failed build skips the release
|
|
49
|
-
- **WHEN** any of the upstream build jobs (test, build-linux, build-windows, or build-wsl) fails
|
|
50
|
-
- **THEN** the release job is skipped and no GitHub Release is created
|
|
51
|
-
|
|
52
|
-
### Requirement: Build Scripts Produce A Working Executable On Bun 1.3.x
|
|
53
|
-
The system MUST provide `bun run build`, `bun run build:linux`, `bun run build:windows`, and `bun run build:release` scripts in `package.json`. Each script MUST produce a single-file executable on Bun 1.3.x when invoked from the repository root. The output binary MUST be executable and MUST report its version when invoked with `--version`.
|
|
54
|
-
|
|
55
|
-
#### Scenario: `bun run build` produces a working executable
|
|
56
|
-
- **WHEN** a developer runs `bun run build` on Bun 1.3.x
|
|
57
|
-
- **THEN** a single-file binary is produced (at `dist/gemiterm` on Linux/macOS or `dist/gemiterm.exe` on Windows) and invoking that binary with `--version` exits 0 and prints the version string
|
|
58
|
-
|
|
59
|
-
#### Scenario: `bun run build:linux` produces an x64 Linux binary
|
|
60
|
-
- **WHEN** a developer runs `bun run build:linux` on Bun 1.3.x
|
|
61
|
-
- **THEN** a Linux x64 single-file binary is produced at `dist/gemiterm` and the binary is executable on a Linux x64 system
|
|
62
|
-
|
|
63
|
-
#### Scenario: `bun run build:windows` produces an x64 Windows binary
|
|
64
|
-
- **WHEN** a developer runs `bun run build:windows` on Bun 1.3.x
|
|
65
|
-
- **THEN** a Windows x64 single-file binary is produced at `dist/gemiterm.exe` and the binary is executable on a Windows x64 system
|
|
66
|
-
|
|
67
|
-
#### Scenario: `bun run build:release` produces a non-debug binary
|
|
68
|
-
- **WHEN** a developer runs `bun run build:release` on Bun 1.3.x
|
|
69
|
-
- **THEN** a minified, single-file binary is produced (without debug symbols or source maps) suitable for distribution
|
|
70
|
-
|
|
71
|
-
### Requirement: Clean Build Scripts Available For Both Platforms
|
|
72
|
-
The system MUST provide `scripts/clean-build.sh` (POSIX shell) and `scripts/clean-build.ps1` (PowerShell) that remove the `dist/` directory and any other transient build artifacts. Each script MUST exit 0 on success and non-zero on error.
|
|
73
|
-
|
|
74
|
-
#### Scenario: POSIX clean-build removes dist and exits 0
|
|
75
|
-
- **WHEN** a developer runs `bash scripts/clean-build.sh` on a POSIX system
|
|
76
|
-
- **THEN** the `dist/` directory is removed (or stays removed if already absent) and the script exits 0
|
|
77
|
-
|
|
78
|
-
#### Scenario: PowerShell clean-build removes dist and exits 0
|
|
79
|
-
- **WHEN** a developer runs `pwsh scripts/clean-build.ps1` on a system with PowerShell Core installed
|
|
80
|
-
- **THEN** the `dist/` directory is removed (or stays removed if already absent) and the script exits 0
|
|
81
|
-
|
|
82
|
-
### Requirement: User-Facing Browser Install Scripts
|
|
83
|
-
The system MUST provide `scripts/install-browser.sh` (POSIX shell) and `scripts/install-browser.ps1` (PowerShell) that run `bunx @playwright/cli install chromium` and verify the installation succeeded. Each script MUST exit 0 on success and non-zero on error. If Chromium is already installed, the script MUST exit 0 without re-downloading.
|
|
84
|
-
|
|
85
|
-
#### Scenario: POSIX install-browser runs the install command
|
|
86
|
-
- **WHEN** a developer runs `bash scripts/install-browser.sh` on a POSIX system with Bun installed
|
|
87
|
-
- **THEN** the script invokes `bunx @playwright/cli install chromium`, reports success to stdout, and exits 0
|
|
88
|
-
|
|
89
|
-
#### Scenario: PowerShell install-browser runs the install command
|
|
90
|
-
- **WHEN** a developer runs `pwsh scripts/install-browser.ps1` on a system with Bun and PowerShell Core installed
|
|
91
|
-
- **THEN** the script invokes `bunx @playwright/cli install chromium`, reports success to stdout, and exits 0
|
|
92
|
-
|
|
93
|
-
#### Scenario: Browser already installed is a no-op
|
|
94
|
-
- **WHEN** a developer runs either install-browser script and Chromium is already installed
|
|
95
|
-
- **THEN** the script exits 0 without re-downloading Chromium and without printing an error
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
## 1. Extend path-utils.ts with the WSL detection, project root, and package.json helpers
|
|
2
|
-
|
|
3
|
-
- [x] 1.1 Add `isWSL(): boolean` to `src/infrastructure/path-utils.ts`. The function MUST gate on `process.platform === 'linux'` and return `true` if `/proc/version` exists and contains "microsoft" or "WSL" (case-insensitive) OR `WSL_DISTRO_NAME` is set and non-empty. The function MUST return `false` on any other platform.
|
|
4
|
-
- [x] 1.2 Add `getProjectRoot(): string` to `src/infrastructure/path-utils.ts`. The function MUST walk up from `import.meta.url` (passed in as a parameter) until it finds a directory containing `package.json`, and return the absolute path. Replaces the `__filename` / `__dirname` dance in `src/cli/index.ts:33-35`.
|
|
5
|
-
- [x] 1.3 Add `getPackageJson(): { name: string; version: string; [key: string]: unknown }` to `src/infrastructure/path-utils.ts`. The function MUST call `getProjectRoot()` + `readTextFile(<root>/package.json)` + `JSON.parse` and return the parsed object. On any error, the function MUST return `{ name: "gemiterm", version: "unknown" }` (the fallback keeps `--version` working in a broken environment).
|
|
6
|
-
|
|
7
|
-
## 2. Create src/infrastructure/io.ts
|
|
8
|
-
|
|
9
|
-
- [x] 2.1 Create `src/infrastructure/io.ts` with the following exports. Each function MUST be a thin wrapper around the equivalent `node:fs` call with consistent semantics (always-recursive `mkdir`, safe returns, clear error messages).
|
|
10
|
-
- `ensureDir(path: string): void` — wraps `mkdirSync(path, { recursive: true })`. Throws on EACCES / EPERM with the absolute path in the error message.
|
|
11
|
-
- `existsFile(path: string): boolean` — wraps `existsSync`.
|
|
12
|
-
- `readTextFile(path: string): string` — wraps `readFileSync(path, 'utf-8')`. Throws a typed `IOError` with the absolute path on ENOENT / EACCES.
|
|
13
|
-
- `safeReadTextFile(path: string): string` — wraps `readFileSync` in a try/catch; returns `""` on any error (ENOENT, EACCES, EISDIR). Includes a code comment that the `""` return conflates "file does not exist" with "file exists but is empty" and is appropriate for callers that only need a string for `.includes()` / `.trim()` checks.
|
|
14
|
-
- `writeTextFile(path: string, content: string): void` — resolves the path, ensures the parent directory exists (recursively), and writes `content` as UTF-8. Throws a typed `IOError` on EACCES / ENOSPC.
|
|
15
|
-
- `readJsonFile<T>(path: string): T` — wraps `readTextFile` + `JSON.parse`. Throws a typed `IOError` with a `cause` field on parse failure.
|
|
16
|
-
- `writeJsonFile(path: string, data: unknown): void` — wraps `writeTextFile` with `JSON.stringify(data, null, 2)`.
|
|
17
|
-
- `removeDir(path: string): void` — wraps `rmSync(path, { recursive: true, force: true })`. No-op if the path does not exist.
|
|
18
|
-
- `renameDir(src: string, dest: string): void` — wraps `renameSync`. Throws on ENOENT (source missing) or EEXIST (dest present) with a clear message.
|
|
19
|
-
- `isDirectory(path: string): boolean` — wraps `statSync(path).isDirectory()` in a try/catch; returns `false` if the path does not exist.
|
|
20
|
-
- `listSubdirectories(path: string): string[]` — wraps `readdirSync` + filter to directories only. Returns `[]` if the path does not exist.
|
|
21
|
-
- [x] 2.2 Define and export a class `IOError extends Error` with a `cause` field for the original error (when applicable). All other functions throw `IOError` instead of raw `Error`.
|
|
22
|
-
- [x] 2.3 Add a JSDoc comment at the top of `io.ts` stating the rule: "This is the canonical home for file-system access in `src/`. No other source file in `src/` may import from `node:fs` or `node:path` directly. The only allowed exception is `src/services/install-browser-service.ts`, which may use `node:path` for the WSL mount parser."
|
|
23
|
-
|
|
24
|
-
## 3. Refactor install-browser-service.ts to use the shared platform module and io.ts
|
|
25
|
-
|
|
26
|
-
- [x] 3.1 In `src/services/install-browser-service.ts`:
|
|
27
|
-
- Delete the private `isWsl()` method (lines 143-149) and the `readFileSafe` helper (lines 173-179).
|
|
28
|
-
- Add imports: `import { isWSL } from "../infrastructure/path-utils.ts";` and `import { existsFile, safeReadTextFile } from "../infrastructure/io.ts";`.
|
|
29
|
-
- Replace every call to `this.isWsl()` with `isWSL()`.
|
|
30
|
-
- Replace every call to `this.readFileSafe(path)` with `safeReadTextFile(path)`.
|
|
31
|
-
- Replace every call to `existsSync(path)` with `existsFile(path)`.
|
|
32
|
-
- Unify `getEdgePaths()` and `getChromePaths()` (lines 84-100) behind a single local helper `getWindowsKnownDirs()` that returns `{ programFiles, localAppData }`. The two methods collapse to ~5 lines each.
|
|
33
|
-
- [x] 3.2 Verify the behavior is preserved. The dispatch logic in `findSystemBrowser` (lines 57-65) and `findLinuxBrowser` (lines 102-122) MUST continue to behave identically. The 5 unit tests in `tests/services/install-browser-service.test.ts` are the regression gate; the 432/432 baseline MUST be preserved.
|
|
34
|
-
- [x] 3.3 Do NOT touch `src/services/playwright-cli-driver.ts`, `src/services/cookie-monitor.ts`, or `src/services/auth-service.ts` in this task — they are sensitive and out of scope.
|
|
35
|
-
|
|
36
|
-
## 4. Refactor storage.ts and config.ts to use io.ts
|
|
37
|
-
|
|
38
|
-
- [x] 4.1 In `src/infrastructure/storage.ts`:
|
|
39
|
-
- Drop the `node:fs` import (lines 1-8).
|
|
40
|
-
- Add `import { ensureDir, existsFile, readJsonFile, writeTextFile, removeDir, renameDir } from "./io.ts";`.
|
|
41
|
-
- `CookieStorage.save()` (lines 52-58) → use `writeTextFile(filePath, JSON.stringify(state, null, 2))`.
|
|
42
|
-
- `CookieStorage.load()` (lines 60-70) → use `readJsonFile<StorageState>(filePath)`.
|
|
43
|
-
- `CookieStorage.delete()` (lines 72-77) → use `removeDir(dir)`.
|
|
44
|
-
- `ProfileManager.create()` (lines 91-101) → use `existsFile` + `ensureDir`.
|
|
45
|
-
- `ProfileManager.delete()` (lines 103-116) → use `removeDir` + `existsFile` + `removeFile` (or `rmSync` on the marker).
|
|
46
|
-
- `ProfileManager.rename()` (lines 118-131) → use `existsFile` + `renameDir`.
|
|
47
|
-
- `ProfileManager.setDefault()` (lines 133-138) → use `existsFile`.
|
|
48
|
-
- `ProfileManager.getStatus()` (lines 148-184) → use `existsFile`.
|
|
49
|
-
- [x] 4.2 In `src/infrastructure/config.ts`:
|
|
50
|
-
- Drop the `node:fs` and `node:path` imports (lines 1-2).
|
|
51
|
-
- Add `import { ensureDir, existsFile, readTextFile, writeTextFile, isDirectory, listSubdirectories } from "./io.ts";`.
|
|
52
|
-
- Drop the alias re-exports from `path-utils.ts` (lines 3-9). Use the `path-utils.ts` exports directly.
|
|
53
|
-
- `getDefaultProfileName()` (lines 23-29) → use `existsFile` + `readTextFile`. Fall back to `"default"` if the marker does not exist.
|
|
54
|
-
- `setDefaultProfileName(name)` (lines 31-36) → use `writeTextFile` + `ensureDir(dirname(marker))`.
|
|
55
|
-
- `listProfiles()` (lines 38-47) → use `listSubdirectories` + filter on `DEFAULT_PROFILE_MARKER`.
|
|
56
|
-
- `ensureConfigDir()` (lines 49-54) → use `ensureDir`.
|
|
57
|
-
- The file should shrink from 64 lines to ~40.
|
|
58
|
-
- [x] 4.3 Run `bun test tests/infrastructure/storage.test.ts` and confirm all 21 tests still pass. The 432/432 baseline MUST be maintained across the full `bun test` run.
|
|
59
|
-
|
|
60
|
-
## 5. Refactor the 4 export commands to use writeTextFile
|
|
61
|
-
|
|
62
|
-
- [x] 5.1 `src/cli/commands/export-command.ts:72-82` — replace the 3-line `resolve + dirname + mkdirSync + writeFileSync` block with a single `writeTextFile(outputPath, content)` call. Drop the `node:fs` and `node:path` imports.
|
|
63
|
-
- [x] 5.2 `src/cli/commands/export-all-command.ts:79-80` — replace `mkdirSync(outputDir, { recursive: true })` with `ensureDir(outputDir)`. Drop the `node:fs` and `node:path` imports.
|
|
64
|
-
- [x] 5.3 `src/cli/commands/export-all-command.ts:96-104` — replace the `writeFileSync(filePath, content, "utf-8")` with `writeTextFile(filePath, content)`.
|
|
65
|
-
- [x] 5.4 `src/cli/commands/export-all-command.ts:177-178` (the `index.md` write) — replace with `writeTextFile(indexPath, lines.join("\n"))`. The `join(outputDir, "index.md")` and `join(outputDir, "index.md")` (line 192, the `console.log`) call remain — these are path operations, which `io.ts` does not own; if the file becomes path-only, keep `node:path` import here.
|
|
66
|
-
- [x] 5.5 `src/cli/commands/list-command.ts:138-143` — replace the `writeOutput` method body with a single `writeTextFile(path, content)` call. Drop the `node:fs` and `node:path` imports.
|
|
67
|
-
- [x] 5.6 `src/cli/commands/fetch-command.ts:121-127` — same as 5.5. Once both 5.5 and 5.6 are converted, they are 2-line methods. Keep the duplication; do not extract a shared helper.
|
|
68
|
-
- [x] 5.7 Run the integration tests in `tests/integration/commands/{export,list,fetch}.test.ts` and `tests/cli/export-all-command.test.ts`; confirm they all still pass.
|
|
69
|
-
|
|
70
|
-
## 6. Refactor cli/index.ts to use getPackageJson()
|
|
71
|
-
|
|
72
|
-
- [x] 6.1 `src/cli/index.ts:3-5` — drop the `node:url`, `node:path`, and `node:fs` imports.
|
|
73
|
-
- [x] 6.2 `src/cli/index.ts:33-35` — replace with a single `const pkg = getPackageJson();` call. Add `import { getPackageJson } from "../infrastructure/path-utils.ts";`.
|
|
74
|
-
- [x] 6.3 Verify the version printed by `--version` is still `2.0.0` (the value in `package.json`). The smoke test in `tests/smoke/smoke.test.ts` is the regression gate.
|
|
75
|
-
|
|
76
|
-
## 7. Add tests for the new helpers
|
|
77
|
-
|
|
78
|
-
- [x] 7.1 Extend `tests/unit/path-utils.test.ts` with the following test groups:
|
|
79
|
-
- `isWSL` — at minimum 4 tests: returns false on non-linux, returns true when `WSL_DISTRO_NAME` is set, returns true when `/proc/version` contains "microsoft" (mock the file), returns false on native Linux.
|
|
80
|
-
- `getProjectRoot` — 2 tests: returns the absolute path of the repo root from `import.meta.url`; returns the same path when called twice (idempotent).
|
|
81
|
-
- `getPackageJson` — 3 tests: returns the parsed `package.json` with `name === "gemiterm"` and `version === "2.0.0"`; returns the fallback when the `package.json` is missing; returns the fallback when the `package.json` is unparseable.
|
|
82
|
-
- [x] 7.2 Create `tests/infrastructure/io.test.ts` with the following test groups (at least 15 tests total):
|
|
83
|
-
- `ensureDir` — creates a directory recursively; creates parent directories that do not exist; throws on EACCES.
|
|
84
|
-
- `existsFile` — returns true for existing files; returns false for missing files; returns false for directories.
|
|
85
|
-
- `readTextFile` — reads an existing file; throws `IOError` on ENOENT.
|
|
86
|
-
- `safeReadTextFile` — returns the file content; returns `""` on ENOENT; returns `""` on EACCES.
|
|
87
|
-
- `writeTextFile` — writes a new file; writes to a nested directory that does not exist; throws `IOError` on EACCES.
|
|
88
|
-
- `readJsonFile` / `writeJsonFile` — round-trip a JSON object; throws on parse failure.
|
|
89
|
-
- `removeDir` — removes a directory recursively; no-op on missing path.
|
|
90
|
-
- `renameDir` — renames a directory; throws when source is missing; throws when destination exists.
|
|
91
|
-
- `isDirectory` — returns true for a directory; returns false for a file; returns false for a missing path.
|
|
92
|
-
- `listSubdirectories` — returns only directories; returns `[]` for missing path; excludes the configured marker file.
|
|
93
|
-
- [x] 7.3 The 19 existing `path-utils.test.ts` tests MUST continue to pass. The 5 existing `install-browser-service.test.ts` tests MUST continue to pass. The 21 `storage.test.ts` tests MUST continue to pass. The 432/432 baseline MUST be maintained across the full `bun test` run (plus the new tests).
|
|
94
|
-
|
|
95
|
-
## 8. Fix package.json build scripts
|
|
96
|
-
|
|
97
|
-
- [x] 8.1 In `package.json:20-22`, change the three `build*` scripts to drop `--outdir` and use `--outfile dist/gemiterm` instead. Add a new `build:release` script that uses `--outfile dist/gemiterm --minify`. The four final scripts MUST be: `build`, `build:linux`, `build:windows`, `build:release`.
|
|
98
|
-
- [x] 8.2 Run `bun run build` on the current host. Verify a single-file binary is produced at `dist/gemiterm` (Linux/macOS) or `dist/gemiterm.exe` (Windows). Run the binary with `--version` and confirm it exits 0 and prints `2.0.0`.
|
|
99
|
-
- [x] 8.3 Run `bun run build:linux` and `bun run build:windows` and confirm the cross-compile produces a Linux binary (`dist/gemiterm`, no extension) and a Windows binary (`dist/gemiterm.exe`, with extension) respectively.
|
|
100
|
-
- [x] 8.4 Run `bun run build:release` and confirm a minified binary is produced.
|
|
101
|
-
|
|
102
|
-
## 9. Add clean-build shell scripts
|
|
103
|
-
|
|
104
|
-
- [x] 9.1 Create `scripts/clean-build.sh` (POSIX) that removes `dist/` and any other transient build artifacts. The script MUST `set -e` to fail on error and MUST exit 0 when the cleanup succeeds (including when `dist/` does not exist).
|
|
105
|
-
- [x] 9.2 Create `scripts/clean-build.ps1` (PowerShell Core) that performs the same cleanup. The script MUST use `$ErrorActionPreference = 'Stop'` and exit 0 on success.
|
|
106
|
-
- [x] 9.3 Run `bash scripts/clean-build.sh` and `pwsh scripts/clean-build.ps1` locally and confirm both exit 0 and remove `dist/`.
|
|
107
|
-
|
|
108
|
-
## 10. Add install-browser shell scripts
|
|
109
|
-
|
|
110
|
-
- [x] 10.1 Create `scripts/install-browser.sh` (POSIX) that runs `bunx @playwright/cli install chromium`, reports the command being run, captures stdout/stderr, and exits 0 on success. If Chromium is already installed, the script MUST exit 0.
|
|
111
|
-
- [x] 10.2 Create `scripts/install-browser.ps1` (PowerShell Core) that performs the same operation.
|
|
112
|
-
- [x] 10.3 Run both scripts locally and confirm they exit 0.
|
|
113
|
-
|
|
114
|
-
## 11. Add .github/workflows/test.yml
|
|
115
|
-
|
|
116
|
-
- [x] 11.1 Create `.github/workflows/test.yml` with `on:` triggers for `pull_request` (any branch) and `push` (branches: `[main]`). Add a single `test` job that runs on `ubuntu-latest` with steps: `actions/checkout@v4`, `oven-sh/setup-bun@v2` with `bun-version: 1.3.13`, `bun install --frozen-lockfile`, `bun test`, `bun run typecheck`, and a final `Enforce path-utils mediation` step that runs:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
! grep -rn --include='*.ts' "from \"node:\\(fs\\|path\\|os\\)\"" src/ \
|
|
120
|
-
| grep -v "src/infrastructure/path-utils.ts" \
|
|
121
|
-
| grep -v "src/services/install-browser-service.ts" \
|
|
122
|
-
| grep -q .
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
This MUST exit 0 (success) when no forbidden imports are present. The check excludes `path-utils.ts` (the canonical home) and `install-browser-service.ts` (the only legitimate cross-platform `node:path` consumer, for the WSL mount parser).
|
|
126
|
-
- [x] 11.2 Add a `concurrency:` block at the workflow top that cancels in-progress runs on the same ref.
|
|
127
|
-
- [x] 11.3 Confirm the workflow file is valid YAML.
|
|
128
|
-
|
|
129
|
-
## 12. Add .github/workflows/build.yml
|
|
130
|
-
|
|
131
|
-
- [x] 12.1 Create `.github/workflows/build.yml` with `on:` triggers for `push` (tags: `['v*']`) and `workflow_dispatch`. Add a `concurrency:` block that cancels in-progress tag builds.
|
|
132
|
-
- [x] 12.2 Add a `build` job with `strategy.matrix.os: [ubuntu-latest, windows-latest]` and `strategy.matrix.target: [bun-linux-x64, bun-windows-x64]` plus an extra `build-wsl` job on `ubuntu-latest` producing a Linux x64 binary. Each job MUST checkout, setup Bun 1.3.13, run `bun install --frozen-lockfile`, run the platform-specific build script, verify the binary exists, report its size, and upload via `actions/upload-artifact@v4` with stable names (`GemiTerm` for Linux/WSL, `GemiTerm.exe` for Windows).
|
|
133
|
-
- [x] 12.3 Add a size verification step that fails the job if the binary is less than 20 MB.
|
|
134
|
-
- [x] 12.4 Confirm the workflow file is valid YAML.
|
|
135
|
-
|
|
136
|
-
## 13. Add .github/workflows/release.yml
|
|
137
|
-
|
|
138
|
-
- [x] 13.1 Create `.github/workflows/release.yml` with `on:` triggers for `push` (tags: `['v*']`) only. Add a `release` job that depends on `test.yml/test` and `build.yml/build` via the `needs:` keyword using the cross-workflow `<workflow>/<job>` pattern.
|
|
139
|
-
- [x] 13.2 Add a `permissions:` block with `contents: write` on the release job. Add steps: `actions/checkout@v4`, `actions/download-artifact@v4` (to fetch `GemiTerm`, `GemiTerm.exe`, `install.sh`, `install.ps1`), a "Determine tag" step, and `softprops/action-gh-release@v2` with `generate_release_notes: true`.
|
|
140
|
-
- [x] 13.3 Confirm the workflow file is valid YAML.
|
|
141
|
-
|
|
142
|
-
## 14. Repo hygiene cleanup
|
|
143
|
-
|
|
144
|
-
- [x] 14.1 Remove the orphan file literally named `{` at the repo root.
|
|
145
|
-
- [x] 14.2 Edit `.gitignore:23` and remove the bare `{` line. Leave a blank line for readability.
|
|
146
|
-
- [x] 14.3 In `package.json`, remove the `"commander": "^15.0.0"` entry. Run `bun install` to regenerate `bun.lock` and confirm `commander` is no longer listed.
|
|
147
|
-
- [x] 14.4 Remove the `src/commands/` directory and its `.gitkeep` file.
|
|
148
|
-
- [x] 14.5 Run `git status` and confirm only the intended files are staged.
|
|
149
|
-
|
|
150
|
-
## 15. README updates
|
|
151
|
-
|
|
152
|
-
- [x] 15.1 Add a "Building from source" section to `README.md` after the "Development" section. Document the `bun run build`, `bun run build:linux`, `bun run build:windows`, and `bun run build:release` scripts and the resulting output paths. State the minimum Bun version as 1.3.13.
|
|
153
|
-
- [x] 15.2 Add a "Release artifacts" section to `README.md` after "Building from source". Document that the v2.0.0 release ships `GemiTerm` (Linux x64), `GemiTerm.exe` (Windows x64), `install.sh`, and `install.ps1` as GitHub Release assets.
|
|
154
|
-
- [x] 15.3 Update the "Development" section to mention `bun run typecheck` and the `scripts/install-browser.{sh,ps1}` wrappers.
|
|
155
|
-
|
|
156
|
-
## 16. Verification
|
|
157
|
-
|
|
158
|
-
- [x] 16.1 Run `bun install --frozen-lockfile` to confirm the lockfile is in sync with `package.json` after the `commander` removal.
|
|
159
|
-
- [x] 16.2 Run `bun test` and confirm the full suite passes (the original 432 tests + the new tests in tasks 7.1 and 7.2; the new baseline should be at least 462 tests).
|
|
160
|
-
- [x] 16.3 Run `bun run typecheck` and confirm zero TypeScript errors. The new `io.ts` exports, the refactored call sites, and the new helpers in `path-utils.ts` MUST NOT introduce any new type errors.
|
|
161
|
-
- [x] 16.4 Run `bun run build`, `bun run build:linux`, `bun run build:windows`, and `bun run build:release` and confirm all four produce working executables.
|
|
162
|
-
- [x] 16.5 Run `bash scripts/clean-build.sh`, `pwsh scripts/clean-build.ps1`, `bash scripts/install-browser.sh`, and `pwsh scripts/install-browser.ps1` and confirm all four exit 0.
|
|
163
|
-
- [ ] 16.6 Open a draft pull request to confirm the `test.yml` workflow runs against the change, including the lint check. The PR MUST NOT be merged until `test.yml` is green.
|
|
164
|
-
- [ ] 16.7 Push a `v2.0.0-rc.1` tag to confirm `release.yml` work end-to-end. Delete the tag and the draft release after verification.
|
package/openspec/config.yaml
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
schema: spec-driven
|
|
2
|
-
|
|
3
|
-
# Project context (optional)
|
|
4
|
-
# This is shown to AI when creating artifacts.
|
|
5
|
-
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
|
6
|
-
# Example:
|
|
7
|
-
# context: |
|
|
8
|
-
# Tech stack: TypeScript, React, Node.js
|
|
9
|
-
# We use conventional commits
|
|
10
|
-
# Domain: e-commerce platform
|
|
11
|
-
|
|
12
|
-
# Per-artifact rules (optional)
|
|
13
|
-
# Add custom rules for specific artifacts.
|
|
14
|
-
# Example:
|
|
15
|
-
# rules:
|
|
16
|
-
# proposal:
|
|
17
|
-
# - Keep proposals under 500 words
|
|
18
|
-
# - Always include a "Non-goals" section
|
|
19
|
-
# tasks:
|
|
20
|
-
# - Break tasks into chunks of max 2 hours
|