Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Improve `sentry init` runtime harness with Dirac-inspired patterns

オープン
#711 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
25/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
静か
技術スタック
bun, typescript

調査の方向性

推奨されているビルド順序から始め、src/lib/init/local-ops.ts と src/lib/init/types.ts から着手し、Verification に記載されたフェーズ固有のテストを実行します。後のフェーズに取りかかる前に、指定された AST ファイルと wizard-runner.ts を確認します。フェーズテスト、統合コマンド、build、typecheck、lint、フルスイートがすべてパスすれば完了です。

索引モデルが issue の本文から書いたものです。

説明

enhancement

Summary

Adopt three patterns from the Dirac coding agent to strengthen the sentry init local runtime:

  1. Content hashing (from line-hashing.ts) — FNV-1a file hashing for stale-read detection
  2. Atomic patchsets with rollback (simplified from CheckpointTracker) — in-memory backup before writes
  3. Tree-sitter AST infrastructure (from services/tree-sitter/) — WASM-based code parsing for local framework detection, entry point discovery, and post-patch syntax validation

What We're NOT Picking

  • Hash-anchored line edits: Requires Mastra protocol changes (server must produce hash-referenced diffs). Out of scope.
  • React Ink TUI: We use Stricli + @clack/prompts. Different paradigm.
  • Full eval harness: The Dirac eval system is benchmark-focused, not applicable.

Phase 1: Content Hashing & Staleness Detection (no new deps)

Goal: Detect when files change between read-files and apply-patchset operations.

New file: src/lib/init/content-hash.ts
  • fnv1a(content: string): string — FNV-1a 32-bit hash → 8-char hex (5 lines, from Dirac's line-hashing.ts)
  • FileSnapshot type — Map<string, string> of path→hash
  • createSnapshot(), recordFile(), isStale() helpers
Modify: src/lib/init/local-ops.ts
  • Add module-scoped FileSnapshot instance, reset per wizard run
  • In readFiles(): record content hash for each file after reading
  • In applyEdits(): before applying edits, re-read the file and check staleness. If stale, log.warn() but continue (the fuzzy replacer may still succeed)
  • Return contentHashes in the read-files result data so the Mastra workflow can optionally use it later
Modify: src/lib/init/types.ts
  • Add optional contentHashes?: Record<string, string> to read-files result shape
New tests
  • test/lib/init/content-hash.test.ts — basic hash consistency
  • test/lib/init/content-hash.property.test.ts — determinism, collision resistance

Phase 2: Atomic Patchsets with Rollback (no new deps)

Goal: If any patch in a patchset fails, restore all previously-applied files.

Modify: src/lib/init/local-ops.ts

Restructure applyPatchset() with in-memory backup:

type FileBackup =
  | { type: 'existed'; path: string; absPath: string; content: string }
  | { type: 'created'; path: string; absPath: string };
  • Before each patch: snapshot the file's current content (or record it as nonexistent)
  • On failure: restore all backups in reverse order (write-back for modify/delete, unlink for create)
  • On success: discard backups

Why in-memory, not git stash?

  • git stash has side effects on user's stash stack
  • The wizard already checks for clean git state in git.ts — users can git checkout . for ultimate recovery
  • Patchsets are small (typically <10 files, <100KB total)
Modify: src/lib/init/types.ts
  • Add rolledBack?: boolean and rollbackErrors?: string[] to LocalOpResult
New test: test/lib/init/local-ops-rollback.test.ts
  • 3-patch patchset where patch #3 fails → verify patches #1 and #2 rolled back
  • Modify + rollback restores original content
  • Create + rollback deletes the file

Phase 3: Tree-sitter AST Infrastructure

Goal: Add WASM-based tree-sitter parsing, lazy-loaded and cached.

New dependency
bun add -d web-tree-sitter

NOT adding tree-sitter-wasms as a dependency. Grammar WASMs downloaded on demand (~250-810KB each, cached in ~/.sentry/grammars/). The web-tree-sitter JS runtime (~60KB) bundles via esbuild. Its WASM runtime (~2.5MB) is also downloaded on demand alongside grammars.

New file: src/lib/ast/parser.ts

Adapted from Dirac's languageParser.ts:

  • EXTENSION_TO_LANGUAGE map — .js→javascript, .ts→typescript, .tsx→tsx, .py→python, .go→go, .rb→ruby, .php→php, .java→java
  • getParser(language) — lazy init of web-tree-sitter, loads grammar WASM on demand
  • parseFile(content, filePath) — returns Parser.Tree | null
  • isAstSupported(filePath) — extension check
  • Two-level cache: language→Parser cache + grammar→WASM cache (same as Dirac)
New file: src/lib/ast/grammar-loader.ts
  • ensureGrammar(language) — checks ~/.sentry/grammars/<version>/, downloads from CDN if missing
  • ensureRuntime() — same for the tree-sitter.wasm runtime
  • CDN source: unpkg.com or GitHub-hosted (configurable)
  • Downloads use fetch() with timeout, write via Bun.write()
New file: src/lib/ast/queries.ts

S-expression queries per language, inspired by Dirac's queries/ directory:

type FrameworkSignal = {
  framework: string;      // 'nextjs', 'express', 'django', etc.
  confidence: number;     // 0.0–1.0
  evidence: string;       // human-readable
  file: string;
  line: number;
};

type EntryPoint = {
  file: string;
  line: number;
  kind: 'server-start' | 'app-export' | 'main-function' | 'sdk-init';
  pattern: string;
};

Functions: detectFramework(), findEntryPoints(), findSentryConfig(), generateOutline()

New file: src/lib/ast/errors.ts
  • AstError extends CliError — for grammar load failures, parse errors
New file: src/lib/ast/index.ts

Barrel re-export.

Build impact
  • web-tree-sitter JS: ~60KB bundled (esbuild handles it)
  • WASM runtime: NOT bundled, downloaded on demand (~2.5MB, cached)
  • Grammar WASMs: NOT bundled, downloaded on demand (~250-810KB each, cached)
  • Net binary size increase: ~60KB (just the JS loader)
New test: test/lib/ast/parser.test.ts
  • Mock grammar download, parse a JS fixture, verify tree exists
  • Unsupported extension returns null

Phase 4: AST-Based Intelligence for Init

Goal: Use tree-sitter to send richer context to the Mastra workflow.

New file: src/lib/init/ast-context.ts
type ProjectAstContext = {
  frameworks: FrameworkSignal[];
  entryPoints: EntryPoint[];
  existingSentry: SentryConfig[];
  fileOutlines: Record<string, string>;
};

async function buildProjectAstContext(
  cwd: string,
  dirListing: DirEntry[]
): Promise<ProjectAstContext | null>

File selection heuristic (scan a targeted subset, not the whole tree):

  1. Known entry point filenames: src/index.ts, src/app.ts, app.py, manage.py, main.go, pages/_app.tsx, app/layout.tsx, next.config.js, etc.
  2. Files matching *sentry*
  3. Fallback: first 5 source files in dirListing
Modify: src/lib/init/wizard-runner.ts

After precomputeDirListing(), before run.startAsync():

let astContext = null;
try {
  const { buildProjectAstContext } = await import("./ast-context.js");
  astContext = await buildProjectAstContext(directory, dirListing);
} catch {
  // AST unavailable — continue without it
}

Pass astContext in inputData to the workflow.

New local-op: parse-files

Register as a new operation type in local-ops.ts for the Mastra workflow to request on-demand AST analysis.

Modify: src/lib/init/types.ts
  • Add ParseFilesPayload type
  • Add to LocalOpPayload union

Phase 5: AST Validation of Applied Patches

Goal: Verify modified files are syntactically valid after patching.

New file: src/lib/init/ast-validation.ts
type ValidationResult = {
  valid: boolean;
  errors: Array<{ line: number; column: number; message: string }>;
};

async function validateSyntax(content: string, filePath: string): Promise<ValidationResult>

Implementation: parse with tree-sitter, walk CST for ERROR/MISSING nodes.

Modify: src/lib/init/local-ops.ts

In applySinglePatch() after writing a modify patch:

const result = await validateSyntax(content, patch.path);
if (!result.valid) {
  log.warn(`Syntax issues in ${patch.path}: ${result.errors.length} error(s)`);
}

Advisory only (warn, don't fail). Validation errors are included in the patchset result metadata so the Mastra workflow can decide whether to retry.


Recommended Build Order

Phase 1 (content hashing)    ─── 1 day, no deps, immediate value
    ↓
Phase 2 (atomic rollback)    ─── 1.5 days, no deps, immediate value
    ↓
Phase 3 (tree-sitter infra)  ─── 3-4 days, adds web-tree-sitter
    ↓
Phase 4 (AST intelligence)   ─── 3-4 days, uses Phase 3
    ↓
Phase 5 (AST validation)     ─── 2 days, uses Phase 3

Phases 1-2 are dependency-free quick wins. Phase 3 is the risky foundation. Phases 4-5 build on it.

Total: ~11-13 days


Key Files Modified

File Phase Change
src/lib/init/local-ops.ts 1,2,4 Content hashing, atomic rollback, parse-files handler
src/lib/init/types.ts 1,2,4 New payload types, result fields
src/lib/init/wizard-runner.ts 4 Pass astContext to workflow
package.json 3 Add web-tree-sitter devDependency

Key Files Created

File Phase
src/lib/init/content-hash.ts 1
src/lib/ast/parser.ts 3
src/lib/ast/grammar-loader.ts 3
src/lib/ast/queries.ts 3
src/lib/ast/errors.ts 3
src/lib/ast/index.ts 3
src/lib/init/ast-context.ts 4
src/lib/init/ast-validation.ts 5

Risks

Risk Level Mitigation
web-tree-sitter WASM loading in Bun compiled binary High Download WASM on demand (not embedded). Test early in Phase 3.
Grammar CDN unreliable Medium Host grammars on GitHub Releases or bundle JS/TS grammars as fallback (~2MB)
Tree-sitter adds complexity for limited init-specific value Medium Phases 1-2 deliver value without tree-sitter. AST phases are additive, not critical path.
Mastra workflow ignores astContext initially Low Context is advisory — server can adopt it incrementally. Local value (validation) is standalone.

Verification

  1. Phase 1: bun test test/lib/init/content-hash — property tests pass
  2. Phase 2: bun test test/lib/init/local-ops-rollback — rollback tests pass
  3. Phase 3: bun test test/lib/ast/parser — JS/TS parsing works
  4. Phase 4: bun test test/lib/init/ast-context — framework detection returns signals
  5. Phase 5: bun test test/lib/init/ast-validation — catches broken syntax
  6. Integration: bun run dev -- init ./test-project --dry-run — wizard completes with AST context
  7. Build: bun run build — binary size increase < 100KB (only JS loader bundled)
  8. Full suite: bun run typecheck && bun run lint && bun test
主要言語
TypeScript
スター
123
フォーク
14
平均マージ
21時間 48分
マージ済み PR(30日)
64

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

getsentry/cli のほかの issue

getsentry/cli の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。