Skip to content

feat(cli): add ci-setup wizard for shared team MCP server onboarding#2102

Open
MCKRUZ wants to merge 21 commits into
abhigyanpatwari:mainfrom
MCKRUZ:feature/ci-setup-wizard
Open

feat(cli): add ci-setup wizard for shared team MCP server onboarding#2102
MCKRUZ wants to merge 21 commits into
abhigyanpatwari:mainfrom
MCKRUZ:feature/ci-setup-wizard

Conversation

@MCKRUZ

@MCKRUZ MCKRUZ commented Jun 9, 2026

Copy link
Copy Markdown

Summary

  • Adds gitnexus ci-setup command that generates all artifacts needed to run GitNexus as a shared, CI/CD-maintained MCP server for a team
  • Supports GitHub Actions + Azure DevOps CI, Docker Compose + Azure Container App deployment, token auth (Caddy proxy) or no-auth modes, and pr-scoped/main-only index strategies
  • 36 passing unit tests; zero new TypeScript errors; idempotent; default dry-run mode

Why @inquirer/prompts (new dependency)

This command's primary value is the interactive onboarding UX — arrow-key menus that guide a developer through 4 decision points before generating files. The existing dep tree has no TTY prompt library (commander handles flags only). @inquirer/prompts v8 is the ESM-native, actively maintained successor to inquirer; it has no native modules, adds ~400 KB to the install, and ships its own TypeScript declarations. All prompts are TTY-gated (process.stdin.isTTY) and the command is fully non-interactive via flags — the dep is purely additive.

Corrections to the original spec

The original design doc contained three factual errors about the codebase. These are corrected here:

Spec claimed Reality Source
serve port 4848 serve defaults to 4747; 4848 is eval-server src/cli/serve.ts:29, src/cli/index.ts:264
Healthcheck GET /health Path is GET /api/health src/server/api.ts:852
GITNEXUS_TOKEN auth env var No auth exists in the server — CORS + rate limiting only src/server/ grep

The --auth token mode generates a Caddy reverse-proxy sidecar that genuinely enforces a bearer token in front of gitnexus (which stays on the internal Docker network and is never published). --auth none publishes port 4747 directly with a warning banner.

Test plan

  • gitnexus ci-setup --dry-run prints all artifact contents, writes nothing
  • gitnexus ci-setup --apply --yes writes all expected files
  • Second --apply --yes run skips all files (exists, identical)
  • --auth none omits Caddyfile and proxy service, shows no-auth banner
  • --ci both --deploy both generates all 6 artifact files
  • Run vitest run test/unit/ci-setup*.test.ts — 36 tests pass

🤖 Generated with Claude Code

Adds `gitnexus ci-setup` — a new command that detects the current repo
environment and generates all artifacts needed to run GitNexus as a shared,
CI/CD-maintained MCP server:

- GitHub Actions workflow (push + PR triggers, node 22, artifact upload)
- Azure DevOps pipeline YAML (with commercial-use notice)
- Docker Compose service using the published ghcr.io image (port 4747)
  - `--auth token`: Caddy reverse-proxy sidecar enforces GITNEXUS_TOKEN
    (gitnexus is internal-only; the proxy publishes port 4748)
  - `--auth none`: direct port 4747 with a no-auth warning banner
- Azure Container App deploy script (az CLI)
- Claude Code HTTP MCP snippet (.claude/gitnexus-mcp-snippet.json)
- GITNEXUS.md onboarding doc with decision log and next steps

Key design decisions:
- Corrects three errors in the original spec: serve port is 4747 (not 4848),
  health endpoint is /api/health (not /health), and GITNEXUS_TOKEN provides
  no auth in the server itself — real auth requires the Caddy proxy layer.
- Adds @inquirer/prompts (v8, ESM-native) for TTY arrow-key prompts; all
  flags work non-interactively for CI/scripted use.
- Default mode is --dry-run (preview only); --apply writes with per-file
  confirmation; --yes skips confirmations for scripted runs.
- Idempotent: second --apply run skips files that are byte-identical.
- 36 passing unit tests covering templates (pure functions, js-yaml parse
  validation) and command behavior (real-fs-in-tempdir, vitest pattern).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@MCKRUZ
MCKRUZ requested a review from magyargergo as a code owner June 9, 2026 01:56
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

@MCKRUZ is attempting to deploy a commit to the NexusCore Team on Vercel.

A member of the Team first needs to authorize it.

@zander-raycraft

Copy link
Copy Markdown
Collaborator

@MCKRUZ Thanks so much, this looks great!! @magyargergo this is a cool concept, lmk your thoughts on it when you get a chance

@magyargergo

Copy link
Copy Markdown
Collaborator

I just shared this with @abhigyanpatwari because i like this idea too. I think we should proceed with this. :)

@magyargergo

Copy link
Copy Markdown
Collaborator

@MCKRUZ Great idea! We really like this PR and will proceed with it.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

✨ PR Autofix

Found fixable formatting / unused-import issues across 22 changed lines. Comment /autofix on this PR to apply them, or run npm run lint:fix && npm run format locally.

{"schema":"gitnexus.pr-autofix/v2","state":"fixes-available","pr_number":2102,"changed_lines":22,"head_sha":"3b3d71dba64fea9499d14a387ba65942a85f7ca3","run_id":"27494710281","apply_command":"/autofix"}

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

CI Report

Some checks failed

Pipeline Status

Stage Status Details
❌ Typecheck failure tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
11992 11934 0 54 756s

✅ All 11934 tests passed

54 test(s) skipped — expand for details

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 76.49% 39623/51795 N/A% 🟢 ███████████████░░░░░
Branches 64.48% 24721/38335 N/A% 🟢 ████████████░░░░░░░░
Functions 82.12% 4299/5235 N/A% 🟢 ████████████████░░░░
Lines 80.16% 35781/44632 N/A% 🟢 ████████████████░░░░

📋 View full run · Generated by CI

@magyargergo magyargergo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tri-review: PR #2102gitnexus ci-setup wizard

Methods: GitNexus swarm (Claude) · Compound-Engineering personas (Claude, including a DevOps/SRE persona per request) · Codex (the one independent, non-Claude engine — ran live). Engine breakdown: 5 substantive Claude lanes + Codex, plus first-hand CI-log verification by the coordinator. Two GitNexus lanes (risk, test/CI) ended mid-investigation; their domains are covered by the CI-log evidence and the other lanes. Claude-lane agreement is consistent, not independent — only Codex is a different engine, so the strongest signals below are "Codex + a Claude lane." This is an automated multi-tool digest; verify before acting.

🔴 CI is red — all three failures are caused by this PR

Verified from the run logs; Codex independently confirmed the mechanisms.

  1. quality / lint (blocking): console.error at ci-setup.ts:38 violates the repo's no-console rule ('no-console': ['error', { allow: ['log'] }], eslint.config.mjs:110). It's the single lint error. → inline
  2. tests / ubuntu / coverage (blocking): the 1 failed test is test/unit/cli-index-help.test.ts ("localizes every registered CLI command…") — the new ci-setup command + 8 options are registered with literal English strings but never added to the CLI i18n bundle, so zh-CN --help renders them in English. → inline
  3. quality / format: prettier fails on 3 new files (ci-setup.ts, ci-setup/prompts.ts, test/unit/ci-setup.test.ts) — run prettier --write.

Headline finding (strong: Codex + 4 Claude lanes + coordinator code-read)

ci-setup --port <non-4747> generates a dead deployment. serve reads its port only from the CLI flag (serve.ts:29 — never process.env.PORT), the production image hardcodes serve --host 0.0.0.0 --port 4747 (Dockerfile.cli:80), and the generated compose never overrides command:. So the container always listens on 4747 while the healthcheck (curl …:${opts.port}/api/health) and the Caddy target (gitnexus:${opts.port}) point at the chosen port. Token mode: container never becomes healthy → the proxy's depends_on: condition: service_healthy never starts. No-auth mode: the published port forwards to nothing. The default (4747) works only by coincidence; the --port flag is a foot-gun. → inline

Also worth fixing

  • Generated GitHub Actions workflow hygiene (Codex + DevOps + reliability + security)npx gitnexus@latest is non-reproducible / a supply-chain surface; no top-level permissions: (least privilege); no concurrency: (the repo enforces a concurrency convention); no timeout-minutes; actions float on @v4 while the repo SHA-pins (v6/v7). → inline
  • --port is never validated (correctness + adversarial; coordinator-verified)parseInt('abc')NaN, and NaN ?? 4747NaN (nullish coalescing doesn't catch NaN), so --port abc templates a literal NaN; --port 65535 → proxy port 65536 (invalid). → inline
  • GITNEXUS.md overstates the CI behavior (Codex + adversarial + DevOps, P1) — it claims the skills/index are "committed to the repository … automatically" (templates.ts:452), but the generated workflow has no git commit/push step.
  • The "stays fresh via CI" loop is never wired (Codex + adversarial + DevOps, P1) — the workflow only uploads .gitnexus/ as a 30-day artifact; nothing delivers it to the server's persistent volume. (The adversarial lane also notes GITNEXUS_HOME is the registry dir, not the per-repo graph at <repo>/.gitnexus, which is mounted :ro.) Either generate a deploy step or correct the doc.
  • Azure ACA deploy script (Codex + reliability + adversarial + DevOps) — default STORAGE_ACCOUNT="gitnexusstorage" is globally unique across Azure (almost certainly taken → az storage account create fails under set -e); not idempotent on re-run; STORAGE_KEY passed as a CLI arg (process-list / log exposure); --ingress internal may make the server unreachable by external MCP clients. The reliability lane flagged the az containerapp create --volume-* / --mount-path flags as possibly invalid for create (needs update/YAML) — unverified; test the ACA path end-to-end before relying on it.
  • MCP snippet is JSONC in a .json file (Codex + DevOps + security, P2).claude/gitnexus-mcp-snippet.json opens with // comments → invalid JSON for any strict parser. Rename to .jsonc or emit comment-free JSON. (No auto-loader consumes the path, so impact is limited to manual/tool parsing.)
  • detect probe hardcodes 4747 (Codex + correctness + DevOps, P3)detect.ts:135 / ci-setup.ts:54 ignore --port; cosmetic, but reinforces the false impression that --port works.
  • Cleartext bearer token over HTTP (DevOps, P2) — fine on localhost, risky for a server reachable beyond the host; document/generate TLS.
  • Non-TTY overwrite prompt (correctness/adversarial, P2/P3)--apply without --yes on a repo with a differing existing file calls inquirer confirm() in a non-TTY context → lands in result.errors; mirror the TTY guard already used for the select prompts.

✅ Validated — credit where due

  • The Caddy token gate fails CLOSED — confirmed independently by Codex + the security lane + the DevOps lane (refuting the adversarial lane's fail-open suspicion): handle sorts before the bare respond catch-all, the header matcher is exact-match, and compose's ${GITNEXUS_TOKEN:?…} blocks startup on an empty token. Minor residual: running the standalone Caddyfile (outside compose) with an empty GITNEXUS_TOKEN would match Bearer — a defense-in-depth nit, not a default-path bug.
  • The command scaffolding (dry-run default, idempotent identical-file skip, per-file error capture, safe non-TTY select defaults) is well-built and tested; the correctness lane explicitly refuted the redundant-nested-if, scan-cap, and fallback-default suspicions as non-bugs.

Test-coverage gaps

Unit tests assert YAML parseability + string-contains, not semantics — nothing catches the --port breakage, the NaN port, the missing permissions:/concurrency:, or validates the Caddyfile/compose against the real image's port contract.

CI status: lint / format / ubuntu coverage failing (all PR-caused, above); Vercel = deploy-auth (not code); everything else green.

Automated tri-review (GitNexus swarm + CE personas + Codex). Treat findings as leads to verify, not verdicts.

Comment thread gitnexus/src/cli/ci-setup.ts Outdated
Comment thread gitnexus/src/cli/index.ts
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
Comment thread gitnexus/src/cli/ci-setup.ts Outdated
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
@magyargergo

Copy link
Copy Markdown
Collaborator

@MCKRUZ Left some comments, and please let me know what you think

magyargergo and others added 3 commits June 9, 2026 09:06
- console.error → console.log (ESLint no-console)
- Add i18n keys for ci-setup command + all 9 options in en.ts, zh-CN.ts,
  help-i18n.ts; add ['ci-setup'] to allHelpCommands in cli-index-help test
- Container port hardcoded to 4747 (image CMD is not overridable); --port
  now controls host binding only; fixes dead deployments with non-4747 ports
- Guard non-TTY overwrite prompt with process.stdin.isTTY check
- Add port range validation (1–65534) with clear error message
- Fix ACA --target-port to 4747 (container port, not host)
- Add permissions/concurrency/timeout-minutes to generated GHA workflow
- Fix GITNEXUS.md false claim about skills being auto-committed
- Strip // comments from MCP snippet (invalid JSON); use _comment/_note keys
- All 48 unit tests passing; prettier check clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
….test.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@magyargergo

Copy link
Copy Markdown
Collaborator

@MCKRUZ Can you please resolve the merge conflicts? 🙏

@MCKRUZ

MCKRUZ commented Jun 11, 2026 via email

Copy link
Copy Markdown
Author

Resolve conflicts in the CLI i18n/registration files where main's new
`uninstall` command collided with this branch's `ci-setup` command —
keep both in src/cli/index.ts, help-i18n.ts, i18n/en.ts, and i18n/zh-CN.ts.

Picks up main's grammar-build consolidation (single
build-tree-sitter-grammars.cjs), busboy upload-ingest, and the
isDeleted/cfgSideChannel scope-resolution additions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MCKRUZ

MCKRUZ commented Jun 11, 2026

Copy link
Copy Markdown
Author

@magyargergo Merge conflicts resolved — merged latest main (e01466b). The conflicts were all the same collision: your new uninstall command vs this branch's ci-setup command in the CLI registration + i18n bundles (index.ts, help-i18n.ts, i18n/en.ts, i18n/zh-CN.ts) — kept both. GitHub now shows the PR as MERGEABLE.

Verified locally before pushing: tsc --noEmit (gitnexus + gitnexus-web), the CLI i18n localization test + ci-setup tests, and eslint (0 errors). The branch's net delta vs main is now just the ci-setup wizard.

Minor heads-up: prettier --check . flags 5 gitnexus-web/src/components/*.tsx files, but they're byte-identical to main and untouched by this PR — looks like pre-existing format drift, not from this branch. Ready for another look 🙏

@magyargergo magyargergo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tri-review: PR #2102gitnexus ci-setup wizard (re-review @ 8666342b)

Engines: 7 Claude reviewer lanes — GitNexus swarm (risk, test/CI, security-boundary) + Compound-Engineering personas (correctness, adversarial, reliability, maintainability). Codex did not return findings this run (it evaporated), so this is an all-Claude, multi-persona review — lane agreement below is consistent across personas, not independent cross-engine confirmation. Each inline finding was verified first-hand by the coordinator (1 reproduced, rest code-read). Automated digest — verify before acting.

Re-review of a moving head. A prior tri-review (2026-06-09 @ b2bc2dc2) is on this PR. Since then the author fixed the CI failures + the port contract, and origin/main was merged in (→ 8666342b). The prior CI-failure findings are resolved (verified locally). The items below are what remains open or is newly surfaced.

✅ Validated / fixed — credit where due

  • Prior 3 CI failures are fixed, verified locally on 8666342b: ESLint clean (no-console satisfied — uses console.log), Prettier clean, tsc clean, and the ci-setup + cli-index-help unit tests pass (50). --port is now validated (isNaN/<1/>65534 → exit).
  • Container port contract is now self-consistent (the correctness lane refuted the old "dead deployment" bug): the container always listens on internal 4747; only the host/proxy port derives from --port. Healthcheck, Caddy target, and the no-auth mapping all agree.
  • Caddy token gate fails CLOSED on the compose path: respond 401 catch-all, exact header match, gitnexus service unpublished, and ${GITNEXUS_TOKEN:?…} blocks startup on an empty token. No template injection (enum/int-validated inputs); the MCP snippet is valid JSON (_comment/_note keys, not //); non-TTY overwrite is guarded; @inquirer/prompts is lazy-loaded (no CLI startup cost).

🔴 Headline (P1) — the "stays fresh via CI" value prop is unwired

The generated CI runs analyze --skills then upload-artifact .gitnexus/ (30-day retention). The generated server reads a persistent volume (gitnexus-data:/data/gitnexus) with the repo mounted :ro. No generated artifact connects the two — no download-artifact, no server-side analyze, no registry population. A team that follows GITNEXUS.md verbatim gets a shared server that serves an empty/initial index indefinitely, with no loud failure. GITNEXUS.md admits the gap in prose — "updated when the volume-sharing mechanism (rsync, artifact download, or live-mount) delivers a fresh index" (templates.ts:467) — but the wizard generates none of those three mechanisms, and the printed "Next steps" (ci-setup.ts) never mention populating the server volume — so the weak doc disclosure does not save a user who follows the wizard exactly. (risk + adversarial + reliability lanes.) → inline

Also open (P2)

  • Interactive wizard silently skips 2 of its 4 questions (correctness; coordinator-reproduced)--auth/--branch-strategy are given commander defaults (index.ts:61-62), so partial.* is always set and promptAuth()/promptBranchStrategy() at prompts.ts:21,23 are unreachable dead code; --ci/--deploy have no default and DO prompt. A TTY user can never choose none/main-only except via flags — defeating the purpose of the interactive wizard. → inline
  • No enum validation on --ci/--deploy/--auth/--branch-strategy (correctness + maintainability) — raw strings are as-cast (ci-setup.ts:59-69); only --port is validated. --auth toekn (typo) silently falls through to the no-auth compose (insecure); --ci githubactions writes no CI file and renders | undefined | in GITNEXUS.md. → inline
  • Cleartext bearer token over HTTP (security + risk) — Caddy listens on a bare :${proxyPort} (plain HTTP, templates.ts:208) and every generated MCP URL is http://; no TLS anywhere. For a "shared, network-reachable" server, the token + all queries traverse the network unencrypted. → inline
  • ACA deploy script fails first-run and is non-idempotent (reliability + adversarial + security) — default STORAGE_ACCOUNT="gitnexusstorage" (templates.ts:243) must be globally unique across Azure → almost certainly taken → az storage account create aborts under set -e after the resource group was already created; no show||create guards. Also STORAGE_KEY on the CLI (process-list exposure), --ingress internal (printed FQDN unreachable by external MCP clients), and a misleading "enable Easy Auth" comment (Easy Auth/AAD ≠ GITNEXUS_TOKEN enforcement). It's a "review and run" script, but the default path fails. → inline
  • GITNEXUS.md doc-accuracy (adversarial + reliability + risk) — "stale-index PRs are blocked at CI" (templates.ts:464) is false (the step only checks [ -f .gitnexus/meta.json ], which analyze just regenerated); and "skill files … are written into the repository by the CI workflow" (:455) contradicts its own next sentence, while permissions: contents: read (:28) would 403 that push. → inline

Lower priority (P3 / body-only)

  • Magic-number duplication (maintainability): container 4747 ×5 in templates.ts, proxy opts.port+1 ×6, image ghcr.io/abhigyanpatwari/gitnexus:latest ×3 — no constants. Values are currently consistent (correctness-verified), so this is debt, not a live bug.
  • detect.ts:135 probes a hardcoded 4747 before --port is known, so the "Port 4747: available" line is wrong/irrelevant when --port differs (display-only).
  • npx gitnexus@latest in both generated workflows is unpinned (a bad publish breaks every consumer's CI). Acceptable as an onboarding default; pinning to the wizard's own version is safer.
  • Hardening: no-auth compose binds 0.0.0.0 (suggest a 127.0.0.1: default); a standalone Caddyfile run without compose has no empty-token guard (the compose path is safe); unset STORAGE_KEY after use; authComment is injected as # ${authComment} where it already begins with # → cosmetic # # double-hash in the ACA script.

Test-coverage gaps

Tests assert file-writing + YAML-parseability + string-contains, not semantics. Nothing covers: the port-contract invariant at the --port 65534 boundary; the dead-prompt TTY path; invalid-enum rejection; bash -n on the generated ACA script; or that GITNEXUS.md claims match the generated workflow.

CI status: the lint/format/test jobs did not re-trigger on the fork merge head (0 check-runs) — only Vercel ran (deploy-auth failure, not code). Locally verified green (above). Re-running the unit-test job on this head is advisable before merge.

Bottom line: mechanically solid (lint/format/tsc/tests green, port contract fixed, token gate fails closed), but not yet production-ready: the P1 makes the feature's central promise silently non-functional, and the interactive-wizard P2 breaks the primary UX path. Most items are template/doc fixes, not redesigns.

Automated multi-lane (all-Claude this run) digest — treat findings as leads to verify, not verdicts.

Comment thread gitnexus/src/cli/index.ts Outdated
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
Comment thread gitnexus/src/cli/ci-setup.ts Outdated
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
Comment thread gitnexus/src/cli/ci-setup/templates.ts Outdated
magyargergo and others added 8 commits June 14, 2026 08:55
The `--auth` and `--branch-strategy` commander options carried default
values ('token'/'pr-scoped'), so the parsed options object always
populated them. ci-setup.ts then always set partial.auth/branchStrategy,
which made promptAuth()/promptBranchStrategy() in resolveOptions
unreachable dead code — the interactive wizard silently asked only 2 of
its 4 questions and a TTY user could never choose none/main-only.

Drop the commander defaults (like --ci/--deploy, which have none and do
prompt); resolveOptions still supplies the token/pr-scoped fallbacks for
non-TTY/CI runs, so non-interactive behavior is unchanged. The resolved
default is now surfaced in the i18n help descriptions instead of the
auto-appended commander "(default: …)" annotation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
--ci/--deploy/--auth/--branch-strategy were cast straight from the raw
commander string (`as AuthMode`, etc.) with no validation — only --port
was checked. A typo like `--auth toekn` is not 'token', so the templates
fell through to the *no-auth* compose, silently producing an
unauthenticated, port-published deployment the user believed was
token-gated; `--ci githubactions` wrote no CI file and rendered a literal
`| undefined |` in GITNEXUS.md.

Add a requireEnum() helper (exact, case-sensitive membership; no
trim/lowercase normalization so `NONE` exits rather than degrading to the
insecure path) called inside each existing option guard, so an omitted
flag still resolves via the prompt/fallback while an explicitly-passed
invalid value exits non-zero.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
detectEnvironment ran checkPortAvailable(4747) eagerly, before options
were parsed, and the result was printed as a hardcoded "Port 4747:
available" line — wrong/irrelevant whenever the user passed a different
--port. Export checkPortAvailable, drop the eager hardcoded probe (and the
now-unused portAvailable field from DetectResult), and probe resolved.port
after option resolution, reporting the actual port. This also removes a
latent real-socket bind on 4747 from the default unit-test path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The container-internal port (4747 ×5), the image reference (×3), and the
Caddy proxy-port arithmetic (opts.port + 1 ×5) were duplicated across the
generated artifacts, so the port contract could drift if one site was
updated and others missed. Hoist CONTAINER_PORT and GITNEXUS_IMAGE
constants and a caddyProxyPort() helper. Generated output is byte-identical
(existing template tests pass unchanged). buildMcpSnippet's auth-conditional
display port (opts.port+1 for token, opts.port for no-auth) is intentionally
left as-is — it is not the Caddy proxy port.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The generated CI uploads .gitnexus/ as a workflow artifact, but nothing
delivers it to the running server's persistent volume — yet GITNEXUS.md
claimed the volume is "updated when the volume-sharing mechanism (rsync,
artifact download, or live-mount) delivers a fresh index", naming three
mechanisms the wizard never generates. A team following the doc verbatim
gets a server serving an empty/stale index forever, with no loud failure.

Replace that prose with an explicit "the wizard does not automate index
delivery — it is a required operator step" statement plus a commented,
target-matched, copy-adaptable example: for Docker, an on-server scheduled
re-index (or `docker compose cp` of the downloaded artifact); for Azure
Container App, `az storage file upload-batch` to the mounted file share.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two generated-doc claims were false:
- "stale-index PRs are blocked at CI" — the step only checks that
  .gitnexus/meta.json exists, which the preceding analyze just
  regenerated, so it never detects staleness and blocks nothing. Reword
  to say it only fails when analyze produced no output, and rename the
  step from "Check index staleness" to "Verify index was produced" in
  both the GitHub Actions and Azure pipeline templates.
- "skill files are written into the repository by the CI workflow" — the
  workflow runs with `permissions: contents: read` and has no commit
  step, so the files are discarded with the runner. State plainly they
  are not auto-committed and that persisting them needs a commit step
  plus `contents: write`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ersion

Generated automation used `npx gitnexus@latest`, which silently pulls
whatever was last published — a non-reproducible single point of failure
for every consumer's CI. Read the wizard's own version from
gitnexus/package.json (the setup.ts MCP_PINNED_REF pattern; read in
ci-setup.ts where ../../package.json resolves correctly, threaded via
CiSetupOptions to avoid a generateFiles signature churn) and pin the
GitHub Actions + Azure pipeline analyze steps and the persisted Cursor
stdio MCP launch to `gitnexus@<version>`. The human-facing manual
re-index commands in GITNEXUS.md intentionally stay `@latest`, matching
setup.ts's "READMEs may use latest, persisted configs are pinned" rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- No-auth docker-compose now publishes via ${GITNEXUS_HOST:-127.0.0.1} so
  it binds loopback by default (not 0.0.0.0) and is not exposed by
  accident; operators set GITNEXUS_HOST to an interface IP / 0.0.0.0 for
  LAN access. The container healthcheck keeps localhost (it curls its own
  loopback, so it must not use GITNEXUS_HOST).
- Caddyfile gains TLS guidance (the proxy is plain HTTP, so the bearer
  token is cleartext — use a hostname for Caddy auto-HTTPS or terminate
  TLS upstream) and a standalone empty-token warning (compose already
  enforces a non-empty GITNEXUS_TOKEN via ${GITNEXUS_TOKEN:?...}).
- GITNEXUS.md (token mode) warns the bearer token travels in cleartext
  and to put the server behind TLS before exposing it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
magyargergo and others added 4 commits June 14, 2026 09:19
ACA deploy script:
- Default STORAGE_ACCOUNT was the global literal "gitnexusstorage", which
  is almost certainly taken (Azure storage names are globally unique) and
  aborts the script under `set -e` after the resource group was created.
  Randomize the first-run default and document setting a fixed name for
  repeatable deploys.
- Make it idempotent: guard each create with `show >/dev/null || create`
  for the storage account, file share, environment, and container app.
- `unset STORAGE_KEY` after registering it (it was passed on the CLI).
- Stop claiming Azure Easy Auth enforces GITNEXUS_TOKEN — it doesn't;
  document that --ingress internal is a VNet boundary and token
  enforcement needs a proxy sidecar.

Connection guidance (KTD-8): buildMcpSnippet and the GITNEXUS.md connect
section branched only on auth, so for `--deploy azure-container-app
--auth token` they advertised a Caddy proxy port (port+1) that does not
exist for ACA and a bearer header ACA never checks. Make them
deploy-aware via mcpServerUrl(): ACA → https://<FQDN>/api/mcp with an
internal-ingress caveat and no bearer header; Docker is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
authComment lines already begin with `#`, but the injection site prefixed
another `# `, producing `# # Auth: …` in the generated bash script. Inject
the comment block without the extra prefix so each line is single-hashed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cross-cutting coverage the per-fix tests don't provide:
- bash -n syntax check on the generated ACA deploy script (catches a
  template regression that produces invalid shell before an operator runs
  it; skipped where bash is unavailable).
- --port upper-boundary: proxy port follows --port (65534 -> 65535) in
  the Caddyfile and MCP snippet, and a base --port of 65535 is rejected
  (its proxy port would exceed the valid range).
- doc/workflow version consistency: workflows + Cursor config pin the same
  version while the manual re-index commands intentionally stay @latest.
- GITNEXUS.md claims match the workflow (no "blocked at CI" / no
  "volume-sharing mechanism" overselling).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants