Compare commits

...

17 Commits

Author SHA1 Message Date
792039e016 Merge pull request 'docs(cli): sync CLAUDE.md — remove stale template text' (#7) from fix/sync-claude-md-state into main 2026-05-11 03:55:41 +00:00
d03845c4ff docs(cli): sync CLAUDE.md — remove stale template text
- Repo state: remove "(2026-04-16): Thin/stub" description
- Section 2: remove "Run tests (none yet...)" and "There is no main.go" notes
- Section 8: mark "Unit tests" and "molecule init" as implemented

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 03:46:55 +00:00
438a04a380 Merge pull request 'docs(cli): update KI-005 — tests now exist (32 integration tests)' (#6) from fix/ki-005-cli-tests-known-issues into main 2026-05-11 03:19:26 +00:00
022cab0dbb docs(cli): update KI-005 — tests now exist (32 integration tests)
known-issues.md claimed "There are no tests at all" but cmd/molecule/
molecule_test.go ships 32 table-driven integration tests covering the
full CLI command surface (workspace CRUD, agent ops, delegation, config,
completion, error paths). Mark KI-005 as resolved.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 03:15:47 +00:00
fd66cb201e Merge pull request 'ci: rename .github/workflows -> .gitea/workflows (post-suspension sweep)' (#5) from ci-rename-github-to-gitea into main
All checks were successful
CI / Test / test (push) Successful in 3m41s
2026-05-10 21:18:07 +00:00
861b562d12 ci: rename .github/workflows -> .gitea/workflows (post-suspension sweep)
All checks were successful
CI / Test / test (pull_request) Successful in 1m39s
Release Go binaries / test (pull_request) Successful in 2m27s
Release Go binaries / release (pull_request) Has been skipped
GitHub org Molecule-AI was suspended 2026-05-06; SCM moved to Gitea
(git.moleculesai.app). The wholesale `git push --mirror` migration left
workflow files under .github/workflows/, which Gitea Actions does NOT
read - it reads .gitea/workflows/ exclusively.

This rename + the cross-repo `uses:` path rewrite are the minimum
edits to make CI fire on this repo again. The workflow content itself
is not modified (other than the path rewrites and lowercasing of the
old `Molecule-AI` org reference to the post-suspension `molecule-ai`).

Refs: feedback_post_suspension_migration_must_sweep_dormant_repos
2026-05-10 14:12:49 -07:00
7badce1740 chore(ci): verify auth fix (revert me) 2026-05-10 20:20:21 +00:00
e562b60d1b chore(ci): auth-test 2 (revert me) 2026-05-10 20:04:17 +00:00
4a84eb3a6b chore(ci): auth-test marker (revert me) 2026-05-10 20:01:54 +00:00
d4ed094c7b chore(ci): remove recovery marker (rerun delivered, see internal#233) 2026-05-10 19:52:10 +00:00
ed089b0c68 chore(ci): re-fire after incident recovery 2026-05-10 (see internal#233; revert me) 2026-05-10 19:51:30 +00:00
09ea1f9ed6 fix(ci): add dedicated CI test workflow (#3)
All checks were successful
CI / Test / test (push) Successful in 10m2s
[sdk-lead-agent] Closes the gap where Go tests only ran on tag push. New ci.yml mirrors release.yml test job (Go 1.25, vet, test -race) on PRs + main pushes; path filters scoped correctly. Self-validation of the workflow passed (1m36s, race-enabled). Approved + merged.
Co-authored-by: Molecule AI SDK-Dev <sdk-dev@agents.moleculesai.app>
Co-committed-by: Molecule AI SDK-Dev <sdk-dev@agents.moleculesai.app>
2026-05-10 09:16:19 +00:00
d587919d17 Merge pull request '[migrate] vanity import go.moleculesai.app/cli (internal#71 phase 2)' (#2) from migrate/issue-71-vanity-imports into main 2026-05-09 00:59:40 +00:00
claude-ceo-assistant
15d8cec45f lint: extend gate to .json files (internal#71 — package metadata drift)
All checks were successful
Release Go binaries / test (pull_request) Successful in 6m18s
Release Go binaries / release (pull_request) Has been skipped
2026-05-07 22:57:16 +00:00
claude-ceo-assistant
76f37d928f fix(post-suspension): vanity import path go.moleculesai.app/cli (closes molecule-ai/internal#71 phase 2)
All checks were successful
Release Go binaries / test (pull_request) Successful in 1m37s
Release Go binaries / release (pull_request) Has been skipped
Migrates go.mod + 22 Go imports + README + comments + generated config
templates off the dead github.com/Molecule-AI/ identity onto the vanity
host go.moleculesai.app, owned by us.

Surfaces touched:
- go.mod module declaration: github.com/Molecule-AI/molecule-cli ->
  go.moleculesai.app/cli
- Every Go import statement under cmd/ + internal/
- README install section: rewritten to lead with the vanity install
  command (the previous text was migration-in-progress hedging)
- Comment URLs in internal/backends/backend.go + internal/cmd/connect.go
  (https://github.com/Molecule-AI/molecule-cli/issues/10) -> point at
  git.moleculesai.app/molecule-ai/molecule-cli
- Generated config templates in internal/cmd/init.go +
  internal/cmd/config.go: header URL updated so new users land on the
  live SCM
- Adds internal/lint/import_path_lint_test.go — structural test that
  walks every *.go / *.mod / Dockerfile / *.md / *.sh / *.yml in the
  module and rejects future references to github.com/Molecule-AI/ or
  Molecule-AI/molecule-monorepo. Mutation-tested before commit.

Test plan
- go build ./... clean
- go test ./... green (cmd/molecule + 5 internal packages + new lint
  gate, all pass)
- TestNoLegacyGitHubImportPaths fails on injected canary, passes on
  clean tree (no tautology)

Open dependency
- go.moleculesai.app responder must be deployed before
  'go install go.moleculesai.app/cli/cmd/molecule@latest' works
  externally. Internal builds + 'go build ./cmd/molecule' from a fresh
  clone work today (self-referential module path).
- Responder code prepared (worker.js, vendor-portable for CF Workers /
  Vercel Edge); deploy tracked separately under internal#71 phase 1.

Pairs with parallel migrations of plugin-gh-identity (#3) +
molecule-controlplane + molecule-core under the same internal#71 sweep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:26:45 +00:00
51fb38e063 Merge pull request 'docs(install): document upcoming Go-module migration + replace install command (#37)' (#1) from fix/install-path-gitea into main 2026-05-07 06:47:07 +00:00
documentation-specialist
2ee3b42d6b docs(install): document upcoming Go-module migration + replace install command (#37)
This PR is README-only. The Go module-path migration
(github.com/Molecule-AI/molecule-cli → git.moleculesai.app/molecule-ai/
molecule-cli in go.mod + every internal import) is filed separately as
a cross-repo Go-module migration PR (parked follow-up on internal#37).

Changes here:
- Install section: keep the go install command but switch to the
  Gitea path + add a "Migration in progress" callout pointing at the
  build-from-source workaround until the Go-module PR lands.
- Releases link: removed the broken github.com/.../releases URL
  (releases pipeline being restored on Gitea Actions).
- RFC #10 link: rewritten to git.moleculesai.app form with note that
  the original issue lived on the suspended GitHub org.

Files NOT touched in this PR (left for the cross-repo Go-module PR):
- go.mod (module declaration)
- 25+ .go files with github.com/Molecule-AI/molecule-cli/internal/...
  import paths
- known-issues.md L96 (describes current module path; consistent with
  go.mod)
- CLAUDE.md L37 (declares current module path; consistent with go.mod)

These edits maintain consistency with go.mod while documenting the
upcoming change to users. Bundling them with the doc edit would create
a half-state where docs say one path and go.mod says another.

Refs: molecule-ai/internal#37, molecule-ai/internal#38
2026-05-06 23:32:47 -07:00
28 changed files with 263 additions and 61 deletions

View File

@ -0,0 +1 @@
ci-auth-test-1778443313

View File

@ -0,0 +1 @@
ci-auth-test2-1778443456

39
.gitea/workflows/ci.yml Normal file
View File

@ -0,0 +1,39 @@
name: CI / Test
# Runs on every PR touching Go code, and on every push to main.
# Mirrors the test job from release.yml so PRs are validated independently
# of the release workflow. Uses Go 1.25 to match release.yml.
on:
push:
branches: [main]
paths:
- '**.go'
- 'go.mod'
- 'go.sum'
- '.github/workflows/ci.yml'
pull_request:
paths:
- '**.go'
- 'go.mod'
- 'go.sum'
- '.github/workflows/ci.yml'
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
cache: true
- name: Tidy
run: go mod tidy && git diff --exit-code go.sum
- name: Vet
run: go vet ./...
- name: Test
run: go test -race -count=1 ./...

View File

@ -0,0 +1 @@
verify-fix-1778444420

View File

@ -4,7 +4,7 @@ Go CLI for the Molecule AI agent platform. Wraps the platform's workspace runtim
**Users:** Platform operators and developers integrating with the Molecule AI platform.
**Repo state (2026-04-16):** Thin/stub. Go module is initialized; core CLI commands are not yet implemented. CI (Go binary release via GoReleaser + GitHub Actions) is wired up.
**Repo state:** Core commands implemented. 32 integration tests in `cmd/molecule/molecule_test.go`.
---
@ -23,18 +23,16 @@ This CLI is the primary user-facing tool for interacting with the Molecule AI pl
# Build the binary to ./bin/molecule (or $GOBIN/molecule)
go build -o bin/molecule ./cmd/molecule
# Run tests (none yet; add as commands are implemented)
# Run tests — uses httptest.Server fixtures, no live platform required
go test ./...
# Run the CLI locally (requires platform env vars — see Section 5)
./bin/molecule --help
```
There is no `main.go` or `cmd/molecule/main.go` yet. Creating it is the first implementation task. The module path will be auto-detected from `go.mod`.
## 3. Go Module Conventions
**Module path:** `github.com/Molecule-AI/molecule-cli` (from `go.mod`)
**Module path:** `go.moleculesai.app/cli` (from `go.mod`)
**Dependency management:**
- Use `go mod tidy` after adding or removing dependencies.
@ -131,8 +129,8 @@ See `known-issues.md` at the repo root for the full tracked list.
- [x] Control plane API client (initialized with `MOLECULE_API_URL`)
- [ ] Workspace runtime client (for dev/proxy mode)
- [ ] Configuration file (e.g., `~/.config/molecule/cli.yaml`) — workspace template per platform rules
- [ ] Unit tests for core command logic
- [ ] `molecule init` (bootstrap local workspace config)
- [x] Unit tests for core command logic (32 integration tests)
- [x] `molecule init` (bootstrap local workspace config)
**Platform constraint reminders (from `constraints-and-rules.md`):**
- Postgres is the source of truth. CLI commands that mutate state ultimately write to Postgres via the control plane.

View File

@ -8,12 +8,23 @@ command, or a mock for CI).
## Install
```bash
go install github.com/Molecule-AI/molecule-cli/cmd/molecule@latest
go install go.moleculesai.app/cli/cmd/molecule@latest
```
Or download a binary from [Releases](https://github.com/Molecule-AI/molecule-cli/releases).
Releases ship Linux/macOS/Windows × amd64/arm64 archives plus a sha256
checksums file (see `.goreleaser.yaml`).
The vanity import path `go.moleculesai.app/cli` resolves via the
Molecules AI go-get responder (issue [internal#71][i71]) to our
canonical SCM at git.moleculesai.app. It is independent of any specific
SCM host — when we move SCMs again, no install command changes.
Alternatively, build from source:
```bash
git clone https://git.moleculesai.app/molecule-ai/molecule-cli.git
cd molecule-cli
go build -o molecule ./cmd/molecule
```
[i71]: https://git.moleculesai.app/molecule-ai/internal/issues/71
## Quick start — connect an external workspace
@ -78,7 +89,7 @@ molecule config view / set CLI defaults
molecule completion generate shell completions
```
The full M1 design is in [RFC #10](https://github.com/Molecule-AI/molecule-cli/issues/10).
The full M1 design is in [RFC #10](https://git.moleculesai.app/molecule-ai/molecule-cli/issues/10) (originally filed on the suspended GitHub org; the issue may be re-filed on Gitea — check the issue tracker for the live discussion).
## License

View File

@ -6,7 +6,7 @@ package main
import (
"os"
"github.com/Molecule-AI/molecule-cli/internal/cmd"
"go.moleculesai.app/cli/internal/cmd"
)
func main() {

2
go.mod
View File

@ -1,4 +1,4 @@
module github.com/Molecule-AI/molecule-cli
module go.moleculesai.app/cli
go 1.25.0

View File

@ -5,7 +5,7 @@
// that registers itself via `Register()` from an `init()` block.
// Runtime selection is done via the --backend flag.
//
// See RFC: https://github.com/Molecule-AI/molecule-cli/issues/10
// See RFC: https://git.moleculesai.app/molecule-ai/molecule-cli/issues/10
package backends
import (

View File

@ -5,8 +5,8 @@ import (
"strings"
"testing"
"github.com/Molecule-AI/molecule-cli/internal/backends"
_ "github.com/Molecule-AI/molecule-cli/internal/backends/mock" // register
"go.moleculesai.app/cli/internal/backends"
_ "go.moleculesai.app/cli/internal/backends/mock" // register
)
func TestRegister_DuplicatePanics(t *testing.T) {

View File

@ -29,8 +29,8 @@ package claudecode
import (
"strings"
"github.com/Molecule-AI/molecule-cli/internal/backends"
exec "github.com/Molecule-AI/molecule-cli/internal/backends/exec"
"go.moleculesai.app/cli/internal/backends"
exec "go.moleculesai.app/cli/internal/backends/exec"
)
func init() {

View File

@ -6,8 +6,8 @@ import (
"strings"
"testing"
"github.com/Molecule-AI/molecule-cli/internal/backends"
_ "github.com/Molecule-AI/molecule-cli/internal/backends/claudecode" // register
"go.moleculesai.app/cli/internal/backends"
_ "go.moleculesai.app/cli/internal/backends/claudecode" // register
)
func requireUnix(t *testing.T) {

View File

@ -41,7 +41,7 @@ import (
"strings"
"time"
"github.com/Molecule-AI/molecule-cli/internal/backends"
"go.moleculesai.app/cli/internal/backends"
)
func init() {

View File

@ -7,8 +7,8 @@ import (
"strings"
"testing"
"github.com/Molecule-AI/molecule-cli/internal/backends"
_ "github.com/Molecule-AI/molecule-cli/internal/backends/exec" // register
"go.moleculesai.app/cli/internal/backends"
_ "go.moleculesai.app/cli/internal/backends/exec" // register
)
// requireUnix skips Windows tests that depend on /bin/sh shell semantics.

View File

@ -14,7 +14,7 @@ import (
"context"
"strings"
"github.com/Molecule-AI/molecule-cli/internal/backends"
"go.moleculesai.app/cli/internal/backends"
)
func init() {

View File

@ -7,7 +7,7 @@ import (
"os"
"text/tabwriter"
"github.com/Molecule-AI/molecule-cli/internal/client"
"go.moleculesai.app/cli/internal/client"
"github.com/spf13/cobra"
)

View File

@ -121,7 +121,7 @@ var configInitCmd = &cobra.Command{
}
func runConfigInit(cmd *cobra.Command, _ []string) error {
const defaultConfig = `# molecule CLI config https://github.com/Molecule-AI/molecule-cli
const defaultConfig = `# molecule CLI config https://git.moleculesai.app/molecule-ai/molecule-cli
#
# All values can be overridden by environment variables:
# MOLECULE_API_URL, MOLECULE_RUNTIME_URL, MOL_OUTPUT, MOL_VERBOSE, etc.

View File

@ -9,11 +9,11 @@ import (
"syscall"
"time"
"github.com/Molecule-AI/molecule-cli/internal/backends"
_ "github.com/Molecule-AI/molecule-cli/internal/backends/claudecode" // register backend
_ "github.com/Molecule-AI/molecule-cli/internal/backends/exec" // register backend
_ "github.com/Molecule-AI/molecule-cli/internal/backends/mock" // register backend
"github.com/Molecule-AI/molecule-cli/internal/connect"
"go.moleculesai.app/cli/internal/backends"
_ "go.moleculesai.app/cli/internal/backends/claudecode" // register backend
_ "go.moleculesai.app/cli/internal/backends/exec" // register backend
_ "go.moleculesai.app/cli/internal/backends/mock" // register backend
"go.moleculesai.app/cli/internal/connect"
"github.com/spf13/cobra"
)
@ -21,7 +21,7 @@ import (
// molecule connect — bridge an external-runtime workspace to a local backend.
//
// The full M1+ design lives in the RFC at
// https://github.com/Molecule-AI/molecule-cli/issues/10. This file owns the
// https://git.moleculesai.app/molecule-ai/molecule-cli/issues/10. This file owns the
// command surface; the wiring (heartbeat, activity poll, dispatch) lands in
// internal/connect/ in subsequent PRs.
// ---------------------------------------------------------------------------
@ -68,7 +68,7 @@ Examples:
molecule connect ws_01HF2K... --backend exec \
--backend-opt cmd="python myhandler.py"
See full design: https://github.com/Molecule-AI/molecule-cli/issues/10`,
See full design: https://git.moleculesai.app/molecule-ai/molecule-cli/issues/10`,
Args: cobra.ExactArgs(1),
RunE: runConnect,
}

View File

@ -40,7 +40,7 @@ func runInit(cmd *cobra.Command, _ []string) error {
if _, err := os.Stat(cfgPath); err == nil {
if initForce {
content := `# molecule CLI configuration https://github.com/Molecule-AI/molecule-cli
content := `# molecule CLI configuration https://git.moleculesai.app/molecule-ai/molecule-cli
#
# All values can be overridden by environment variables:
# MOLECULE_API_URL, MOLECULE_RUNTIME_URL, MOL_OUTPUT, MOL_VERBOSE, etc.
@ -69,7 +69,7 @@ func runInit(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("init: %s already exists — not overwriting (use --force to replace)", cfgPath)
}
content := `# molecule CLI configuration https://github.com/Molecule-AI/molecule-cli
content := `# molecule CLI configuration https://git.moleculesai.app/molecule-ai/molecule-cli
#
# All values can be overridden by environment variables:
# MOLECULE_API_URL, MOLECULE_RUNTIME_URL, MOL_OUTPUT, MOL_VERBOSE, etc.

View File

@ -8,7 +8,7 @@ import (
"os"
"text/tabwriter"
"github.com/Molecule-AI/molecule-cli/internal/client"
"go.moleculesai.app/cli/internal/client"
"github.com/spf13/cobra"
)

View File

@ -7,7 +7,7 @@ import (
"os"
"text/tabwriter"
"github.com/Molecule-AI/molecule-cli/internal/client"
"go.moleculesai.app/cli/internal/client"
"github.com/spf13/cobra"
)

View File

@ -9,7 +9,7 @@ import (
"sync"
"time"
"github.com/Molecule-AI/molecule-cli/internal/backends"
"go.moleculesai.app/cli/internal/backends"
)
// Options carries the runtime knobs Run needs. Constructed by the cmd

View File

@ -13,9 +13,9 @@ import (
"testing"
"time"
"github.com/Molecule-AI/molecule-cli/internal/backends"
_ "github.com/Molecule-AI/molecule-cli/internal/backends/mock" // register mock for tests
"github.com/Molecule-AI/molecule-cli/internal/connect"
"go.moleculesai.app/cli/internal/backends"
_ "go.moleculesai.app/cli/internal/backends/mock" // register mock for tests
"go.moleculesai.app/cli/internal/connect"
)
// fakeServer is the minimum workspace-server stub the loops need:

View File

@ -5,7 +5,7 @@ import (
"path/filepath"
"testing"
"github.com/Molecule-AI/molecule-cli/internal/connect"
"go.moleculesai.app/cli/internal/connect"
)
func TestState_LoadMissingReturnsZero(t *testing.T) {

View File

@ -0,0 +1,146 @@
// Issue molecule-ai/internal#71 lint gate.
//
// Walks every *.go file in the module + the go.mod declaration + any
// Dockerfile in the repo, and rejects any reference to the dead
// github.com/Molecule-AI/* identity (or the historical
// Molecule-AI/molecule-monorepo path).
//
// We had a 374+131+30+1-line "github.com/Molecule-AI/" footprint across
// the org pre-migration. The class of bug this gate prevents:
//
// - copy-pastes from old branches re-introducing the dead path
// - Dockerfile -ldflags strings drifting back to github.com on a
// refactor (the path has to match the module declaration to inject
// buildinfo correctly; if they disagree the binary builds but
// reports a wrong / stale GitSHA)
// - new modules added to the repo with the wrong import root because
// someone copied an old go.mod without thinking
//
// Why not just a CI shell grep: a Go test runs everywhere `go test ./...`
// runs, including local pre-push hooks and contributor IDEs. The gate
// fires immediately, with a per-file message that points at the line —
// CI shell grep failures are silent until the runner picks them up.
package lint
import (
"os"
"path/filepath"
"strings"
"testing"
)
// forbiddenSubstrings is the literal-match list. Each string MUST NOT
// appear anywhere under the module root. Entries are checked with
// substring matching, not regex — keep the patterns specific enough
// that a false-positive needs an explicit allowlist entry.
var forbiddenSubstrings = []string{
"github.com/Molecule-AI/",
"Molecule-AI/molecule-monorepo",
}
// allowlistedFiles is the per-file escape hatch. Empty by default —
// add an entry only when there is a documented reason a forbidden
// string MUST appear (e.g. a regression-test fixture that asserts
// the lint gate itself rejects the string). Each entry MUST be
// accompanied by a comment explaining why.
var allowlistedFiles = map[string]bool{
// (intentionally empty — add only with justification)
}
func TestNoLegacyGitHubImportPaths(t *testing.T) {
moduleRoot, err := findModuleRoot()
if err != nil {
t.Fatalf("findModuleRoot: %v", err)
}
checkExt := map[string]bool{
".go": true,
".mod": true,
".sum": false, // go.sum is auto-generated, refs flow from go.mod
".sh": true,
".yml": true,
".yaml": true,
".toml": true,
".md": true,
".json": true, // package.json / tsconfig.json — catches ref drift in package metadata
}
checkBasename := map[string]bool{
"Dockerfile": true,
"Dockerfile.tenant": true,
}
violations := 0
walkErr := filepath.Walk(moduleRoot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
// Skip vendor + .git + node_modules — not our code.
base := info.Name()
if base == "vendor" || base == ".git" || base == "node_modules" || base == "testdata" {
return filepath.SkipDir
}
return nil
}
ext := filepath.Ext(path)
base := filepath.Base(path)
if !checkExt[ext] && !checkBasename[base] {
return nil
}
rel, _ := filepath.Rel(moduleRoot, path)
if allowlistedFiles[rel] {
return nil
}
// Skip the lint test itself — it legitimately names the forbidden
// strings as match patterns.
if strings.HasSuffix(rel, "import_path_lint_test.go") {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
text := string(data)
for _, bad := range forbiddenSubstrings {
if strings.Contains(text, bad) {
// Find the line number for a useful error message.
for lineNo, line := range strings.Split(text, "\n") {
if strings.Contains(line, bad) {
t.Errorf("%s:%d — forbidden substring %q (use go.moleculesai.app/<area>/... per molecule-ai/internal#71)", rel, lineNo+1, bad)
violations++
break
}
}
}
}
return nil
})
if walkErr != nil {
t.Fatalf("walk: %v", walkErr)
}
if violations > 0 {
t.Logf("Total violations: %d. Add to allowlistedFiles ONLY with a documented justification.", violations)
}
}
// findModuleRoot walks up from the test's CWD to find go.mod. The Go
// test harness sets CWD to the package directory; the module root may
// be one or more parents up.
func findModuleRoot() (string, error) {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
dir := cwd
for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir, nil
}
parent := filepath.Dir(dir)
if parent == dir {
return "", os.ErrNotExist
}
dir = parent
}
}

View File

@ -93,7 +93,7 @@ entries may cause CI divergence or checksum mismatches.
### Impact
`go mod verify` in CI may fail if `go.sum` has extra entries not in the
lock file. Additionally, if the module path (`github.com/Molecule-AI/molecule-cli`)
lock file. Additionally, if the module path (`go.moleculesai.app/cli`)
is referenced via `replace` directives from other repos, those references may
persist stale entries.
@ -130,24 +130,29 @@ is set to `.` (repo root) since the main package is at `cmd/molecule`.
## KI-005 — No integration test for the full CLI lifecycle
**File:** `tests/` (does not exist)
**Status:** Not yet implemented
**File:** `cmd/molecule/molecule_test.go`, `internal/`
**Status:** ✅ Resolved
**Severity:** Medium
### Symptom
There are no tests at all (per `go test ./...` — no packages match).
As subcommands are built, there is no test harness for end-to-end CLI testing
(e.g. `molecule workspace create --name test --output json` → verify JSON output).
### Resolution
`cmd/molecule/molecule_test.go` contains 32 table-driven integration tests
covering the full CLI command surface. Each test:
- Starts a `httptest.Server` that mirrors the platform REST API (workspace CRUD,
agent inspection, delegation, health, audit, config, completion scripts).
- Builds the `molecule` binary via `go build -o <tempdir>/molecule .`
- Executes it with `exec.Command` and validates stdout/stderr output.
### Impact
Each subcommand will be shipped without regression protection. Manual testing
is required for every release. The absence of a `tests/` directory also means
there is no fixture for CLI integration testing with recorded API responses.
Test coverage includes:
- Root help, workspace/agent/platform/config help
- `workspace list`, `workspace inspect`, `workspace create`, `workspace delete`,
`workspace restart`, `workspace audit`, `workspace delegate`
- `agent list`, `agent inspect`, `agent send`, `agent peers`
- `platform health`, `platform audit`
- `config init`, `config list`
- `init`, `init --force`
- `completion bash/zsh/fish/powershell`
- Error paths: missing workspace, missing agent, unknown subcommand,
missing required args, duplicate init
### Suggested fix
Add `tests/` with:
- `cmd/molecule/molecule_test.go` — table-driven tests for each subcommand
using `exec.Command("molecule", ...)` against a built binary
- Use `molecule-sdk-python` fixture server or recorded API responses for
offline testing
- Add `go test ./...` to CI; require >0 test packages before merge
Run `go test ./...` from the repo root to execute. No live platform required —
all tests use `httptest.Server` fixtures.