Commit Graph

3 Commits

Author SHA1 Message Date
Tom Boucher
918f987a19 feat(#2982): extend no-source-grep lint to catch var-binding readFileSync.includes() (#2985)
* feat(#2982): extend no-source-grep lint to catch var-binding readFileSync.includes()

The base lint (scripts/lint-no-source-grep.cjs) only catches
readFileSync(...).<text-method>() chained directly. The much more
common var-binding form escapes it:

  const src = fs.readFileSync(p, 'utf8');
  // 50 lines later
  if (src.includes('foo')) {}        // ← still grep, lint missed it

Scan of the test suite found ~141 files using this pattern.

Implementation built TDD per #2982 with structured-IR assertions:

  scripts/lint-no-source-grep-extras.cjs
    - detectVarBindingViolations(src) — pure detector, two passes:
      pass 1 collects vars bound from readFileSync, pass 2 finds any
      <var>.<includes|startsWith|endsWith|match|search>( on those vars.
    - detectWrappedAssertOkMatch(src) — flags
      assert.ok(<expr>.match(...)) which escapes the assert.match rule.
    - VIOLATION enum exposes stable codes for tests to assert on.

  scripts/lint-no-source-grep.cjs
    - Wires the new detectors into the existing per-file check; one
      additional violation row per file with the first 3 sample tokens.

  tests/bug-2982-lint-var-binding.test.cjs
    - 13 tests, all assertions on typed VIOLATION enum / structured
      records. Covers all 5 text-match methods, multi-var, no-bind,
      string literal (must NOT trigger), wrapped assert.ok(.match),
      and assert.match (must NOT double-flag).

Migration backlog (#2974 expanded scope):

  - 42 files annotated `// allow-test-rule: source-text-is-the-product`
    (legitimate — they read .md/.json/.yml files whose deployed text
    IS the product)
  - 3 files annotated `// allow-test-rule: pending-migration-to-typed-ir [#2974]`
    (read .cjs/.js source — clear migration debt)
  - 95 files annotated `pending-migration-to-typed-ir [#2974]` with
    `Per-file review may reclassify as source-text-is-the-product
    during migration` (mixed — manual review under #2974)

After this lands the lint reports 0 violations on main; new
violations in PRs surface immediately.

Closes #2982
Refs #2974

* test(#2982): fix truncated test name per CR

The label ended with a bare '(' from a copy-paste mishap. Now reads
'does NOT flag .matchAll(...) — matchAll is not match, so
assert.ok(.matchAll(...)) is not flagged'.

* chore(#2982): add changeset fragment for PR #2985

* chore(#2982): add changeset fragment for PR #2985
2026-05-01 19:50:10 -04:00
Berkay Karaman
d85a42c7ad fix(install): guard writeSettings against null settingsPath for cline runtime (#2035)
* fix(install): guard writeSettings against null settingsPath for cline runtime

Cline returns settingsPath: null from install() because it uses .clinerules
instead of settings.json. The finishInstall() guard was missing !isCline,
causing a crash with ERR_INVALID_ARG_TYPE when installing with the cline runtime.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* test(cline): add regression tests for ERR_INVALID_ARG_TYPE null settingsPath guard

Adds two regression tests to tests/cline-install.test.cjs for gsd-build/get-shit-done#2044:
- Assert install(false, 'cline') does not throw ERR_INVALID_ARG_TYPE
- Assert settings.json is not written for cline runtime

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* test(cline): fix regression tests to directly call finishInstall with null settingsPath

The previous regression tests called install() which returns early for cline
before reaching finishInstall(), so the crash was never exercised. Fix by:
- Exporting finishInstall from bin/install.js
- Calling finishInstall(null, null, ..., 'cline') directly so the null
  settingsPath guard is actually tested

Tests now fail (ERR_INVALID_ARG_TYPE) without the fix and pass with it.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:58:16 -04:00
Tom Boucher
aa3e9cfaf4 feat(install): add Cline as a first-class runtime (#1991) (#2032)
Cline was documented as a supported runtime but was absent from
bin/install.js. This adds full Cline support:

- Registers --cline CLI flag and adds 'cline' to --all list
- Adds getDirName/getConfigDirFromHome/getGlobalDir entries (CLINE_CONFIG_DIR env var respected)
- Adds convertClaudeToCliineMarkdown() and convertClaudeAgentToClineAgent()
- Wires Cline into copyWithPathReplacement(), install(), writeManifest(), finishInstall()
- Local install writes to project root (like Claude Code), not .cline/ subdirectory
- Generates .clinerules at install root with GSD integration rules
- Installs get-shit-done engine and agents with path/brand replacement
- Adds Cline as option 4 in interactive menu (13-runtime menu, All = 14)
- Updates banner description to include Cline
- Exports convertClaudeToCliineMarkdown and convertClaudeAgentToClineAgent for testing
- Adds tests/cline-install.test.cjs with 17 regression tests
- Updates multi-runtime-select, copilot-install, kilo-install tests for new option numbers

Fixes #1991

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:47:22 -04:00