@specship/specship-darwin-arm64 0.29.0 → 0.30.0
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/bin/specship +1 -1
- package/lib/dist/.claude-plugin/plugin.json +15 -3
- package/lib/dist/activation/cheatsheet.d.ts +10 -7
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +21 -5
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +75 -2
- package/lib/dist/activation/hook-output.d.ts.map +1 -1
- package/lib/dist/activation/hook-output.js +114 -3
- package/lib/dist/activation/hook-output.js.map +1 -1
- package/lib/dist/activation/search-intercept.d.ts +20 -7
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +27 -5
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +7 -4
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +10 -8
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/agents/detect.d.ts +32 -0
- package/lib/dist/agents/detect.d.ts.map +1 -0
- package/lib/dist/agents/detect.js +54 -0
- package/lib/dist/agents/detect.js.map +1 -0
- package/lib/dist/agents/recent-project.d.ts +18 -0
- package/lib/dist/agents/recent-project.d.ts.map +1 -0
- package/lib/dist/agents/recent-project.js +92 -0
- package/lib/dist/agents/recent-project.js.map +1 -0
- package/lib/dist/analytics/canonical-tools.d.ts +23 -0
- package/lib/dist/analytics/canonical-tools.d.ts.map +1 -0
- package/lib/dist/analytics/canonical-tools.js +36 -0
- package/lib/dist/analytics/canonical-tools.js.map +1 -0
- package/lib/dist/analytics/canonical-tools.json +16 -0
- package/lib/dist/analytics/specship-impact.d.ts +3 -2
- package/lib/dist/analytics/specship-impact.d.ts.map +1 -1
- package/lib/dist/analytics/specship-impact.js +6 -4
- package/lib/dist/analytics/specship-impact.js.map +1 -1
- package/lib/dist/bin/specship.js +215 -170
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/bin/uninstall.js +2 -2
- package/lib/dist/bin/uninstall.js.map +1 -1
- package/lib/dist/claudemd/audit.d.ts +12 -3
- package/lib/dist/claudemd/audit.d.ts.map +1 -1
- package/lib/dist/claudemd/audit.js +65 -22
- package/lib/dist/claudemd/audit.js.map +1 -1
- package/lib/dist/commands/specship/spec.md +9 -0
- package/lib/dist/db/migrations.d.ts +1 -1
- package/lib/dist/db/migrations.d.ts.map +1 -1
- package/lib/dist/db/migrations.js +18 -4
- package/lib/dist/db/migrations.js.map +1 -1
- package/lib/dist/db/schema.sql +8 -0
- package/lib/dist/db/spec-queries.d.ts +13 -1
- package/lib/dist/db/spec-queries.d.ts.map +1 -1
- package/lib/dist/db/spec-queries.js +21 -0
- package/lib/dist/db/spec-queries.js.map +1 -1
- package/lib/dist/enforce/changed-files.d.ts +7 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -1
- package/lib/dist/enforce/changed-files.js +17 -0
- package/lib/dist/enforce/changed-files.js.map +1 -1
- package/lib/dist/enforce/enforce.d.ts +35 -1
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +66 -2
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +50 -4
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +105 -13
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/parse-warnings.d.ts +16 -0
- package/lib/dist/extraction/parse-warnings.d.ts.map +1 -0
- package/lib/dist/extraction/parse-warnings.js +30 -0
- package/lib/dist/extraction/parse-warnings.js.map +1 -0
- package/lib/dist/extraction/tree-sitter.d.ts +27 -0
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +168 -1
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/health/smoke-check.js +1 -1
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/hooks/hooks.json +16 -1
- package/lib/dist/index.d.ts +63 -3
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +235 -9
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/agent-record.d.ts +80 -0
- package/lib/dist/installer/agent-record.d.ts.map +1 -0
- package/lib/dist/installer/agent-record.js +351 -0
- package/lib/dist/installer/agent-record.js.map +1 -0
- package/lib/dist/installer/auto-migrate.d.ts +56 -0
- package/lib/dist/installer/auto-migrate.d.ts.map +1 -0
- package/lib/dist/installer/auto-migrate.js +328 -0
- package/lib/dist/installer/auto-migrate.js.map +1 -0
- package/lib/dist/installer/index.d.ts +37 -8
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +156 -46
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +4 -3
- package/lib/dist/installer/install-defaults.d.ts.map +1 -1
- package/lib/dist/installer/install-defaults.js +6 -5
- package/lib/dist/installer/install-defaults.js.map +1 -1
- package/lib/dist/installer/{config-writer.d.ts → targets/claude-config-writer.d.ts} +1 -1
- package/lib/dist/installer/targets/claude-config-writer.d.ts.map +1 -0
- package/lib/dist/installer/{config-writer.js → targets/claude-config-writer.js} +7 -6
- package/lib/dist/installer/targets/claude-config-writer.js.map +1 -0
- package/lib/dist/installer/targets/claude-projects.d.ts +9 -0
- package/lib/dist/installer/targets/claude-projects.d.ts.map +1 -0
- package/lib/dist/installer/targets/claude-projects.js +151 -0
- package/lib/dist/installer/targets/claude-projects.js.map +1 -0
- package/lib/dist/installer/targets/claude.d.ts +28 -1
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +39 -20
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/feature-parity.d.ts +28 -0
- package/lib/dist/installer/targets/feature-parity.d.ts.map +1 -0
- package/lib/dist/installer/targets/feature-parity.js +32 -0
- package/lib/dist/installer/targets/feature-parity.js.map +1 -0
- package/lib/dist/installer/{gemini-commands.d.ts → targets/gemini-commands.d.ts} +7 -3
- package/lib/dist/installer/targets/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/{gemini-commands.js → targets/gemini-commands.js} +35 -14
- package/lib/dist/installer/targets/gemini-commands.js.map +1 -0
- package/lib/dist/installer/targets/gemini-projects.d.ts +11 -0
- package/lib/dist/installer/targets/gemini-projects.d.ts.map +1 -0
- package/lib/dist/installer/targets/gemini-projects.js +84 -0
- package/lib/dist/installer/targets/gemini-projects.js.map +1 -0
- package/lib/dist/installer/targets/gemini.d.ts +94 -8
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +392 -33
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/registry.d.ts +8 -1
- package/lib/dist/installer/targets/registry.d.ts.map +1 -1
- package/lib/dist/installer/targets/registry.js +14 -5
- package/lib/dist/installer/targets/registry.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +44 -1
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +130 -3
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +23 -1
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +22 -2
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +54 -9
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/board-first.d.ts +15 -2
- package/lib/dist/jira/board-first.d.ts.map +1 -1
- package/lib/dist/jira/board-first.js +16 -0
- package/lib/dist/jira/board-first.js.map +1 -1
- package/lib/dist/jira/ci-publish.d.ts +72 -0
- package/lib/dist/jira/ci-publish.d.ts.map +1 -0
- package/lib/dist/jira/ci-publish.js +162 -0
- package/lib/dist/jira/ci-publish.js.map +1 -0
- package/lib/dist/jira/publish.d.ts +23 -0
- package/lib/dist/jira/publish.d.ts.map +1 -1
- package/lib/dist/jira/publish.js +0 -0
- package/lib/dist/jira/publish.js.map +1 -1
- package/lib/dist/jira/regression-pack.d.ts.map +1 -1
- package/lib/dist/jira/regression-pack.js +7 -1
- package/lib/dist/jira/regression-pack.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +8 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +8 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts.map +1 -1
- package/lib/dist/knowledge/enforce.js +6 -1
- package/lib/dist/knowledge/enforce.js.map +1 -1
- package/lib/dist/mcp/jira-tools.d.ts +5 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +59 -4
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +2 -1
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -10
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +69 -20
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.d.ts +11 -0
- package/lib/dist/mcp/session.d.ts.map +1 -1
- package/lib/dist/mcp/session.js +43 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +8 -0
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/reflect/apply.d.ts +2 -2
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +6 -5
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +28 -15
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/session-outcomes.d.ts.map +1 -1
- package/lib/dist/reflect/session-outcomes.js +8 -3
- package/lib/dist/reflect/session-outcomes.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +25 -5
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +7 -0
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.d.ts +14 -2
- package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.js +13 -3
- package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
- package/lib/dist/server/canonical-tools.js +50 -0
- package/lib/dist/server/cli.js +2 -2
- package/lib/dist/server/host-profiles.js +39 -0
- package/lib/dist/server/ingest/index.js +2 -1
- package/lib/dist/server/ingest/ingestor.js +195 -76
- package/lib/dist/server/ingest/project-paths.js +8 -2
- package/lib/dist/server/ingest/recorded-projects.js +43 -0
- package/lib/dist/server/ingest/specship-classify.js +7 -2
- package/lib/dist/server/ingest/transcripts/claude-jsonl.js +54 -0
- package/lib/dist/server/ingest/transcripts/claude.js +64 -0
- package/lib/dist/server/ingest/transcripts/gemini.js +469 -0
- package/lib/dist/server/ingest/transcripts/index.js +14 -0
- package/lib/dist/server/ingest/{parser.js → transcripts/shared.js} +3 -49
- package/lib/dist/server/ingest/transcripts/types.js +4 -0
- package/lib/dist/server/ingest/watcher.js +31 -30
- package/lib/dist/server/routes/claude.js +27 -10
- package/lib/dist/server/routes/graph.js +64 -3
- package/lib/dist/server/routes/mcp.js +57 -15
- package/lib/dist/server/routes/memory.js +54 -35
- package/lib/dist/server/routes/projects.js +78 -7
- package/lib/dist/server/routes/spec.js +125 -0
- package/lib/dist/server/server.js +8 -2
- package/lib/dist/skills/spec-author/SKILL.md +1 -1
- package/lib/dist/skills/spec-author/references/gap-questions.md +1 -1
- package/lib/dist/spec-lint/lint.d.ts +26 -1
- package/lib/dist/spec-lint/lint.d.ts.map +1 -1
- package/lib/dist/spec-lint/lint.js +96 -7
- package/lib/dist/spec-lint/lint.js.map +1 -1
- package/lib/dist/sync/worktree.d.ts +48 -0
- package/lib/dist/sync/worktree.d.ts.map +1 -1
- package/lib/dist/sync/worktree.js +109 -0
- package/lib/dist/sync/worktree.js.map +1 -1
- package/lib/dist/ui/assets/bricolage-latin-C23fTOVi.woff2 +0 -0
- package/lib/dist/ui/assets/bricolage-latin-ext-B82pxkPf.woff2 +0 -0
- package/lib/dist/ui/assets/index-54vorjyq.css +1 -0
- package/lib/dist/ui/assets/index-BZQonCVb.js +52 -0
- package/lib/dist/ui/assets/space-grotesk-latin-DPT1xrvW.woff2 +0 -0
- package/lib/dist/ui/assets/space-grotesk-latin-ext-wJGaI8U0.woff2 +0 -0
- package/lib/dist/ui/index.html +2 -2
- package/lib/dist/update/updater.d.ts +6 -0
- package/lib/dist/update/updater.d.ts.map +1 -1
- package/lib/dist/update/updater.js +13 -1
- package/lib/dist/update/updater.js.map +1 -1
- package/lib/dist/workflows/agents/claude.d.ts +9 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -1
- package/lib/dist/workflows/agents/claude.js +22 -3
- package/lib/dist/workflows/agents/claude.js.map +1 -1
- package/lib/dist/workflows/agents/gemini-version.d.ts +18 -0
- package/lib/dist/workflows/agents/gemini-version.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini-version.js +81 -0
- package/lib/dist/workflows/agents/gemini-version.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +1 -1
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -1
- package/lib/dist/workflows/agents/gemini.js +12 -2
- package/lib/dist/workflows/agents/gemini.js.map +1 -1
- package/lib/dist/workflows/agents/index.d.ts +2 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -1
- package/lib/dist/workflows/agents/index.js +5 -0
- package/lib/dist/workflows/agents/index.js.map +1 -1
- package/lib/dist/workflows/agents/types.d.ts +13 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -1
- package/lib/dist/workflows/agents/types.js.map +1 -1
- package/lib/dist/workflows/condition-evaluator.d.ts +8 -0
- package/lib/dist/workflows/condition-evaluator.d.ts.map +1 -1
- package/lib/dist/workflows/condition-evaluator.js +7 -0
- package/lib/dist/workflows/condition-evaluator.js.map +1 -1
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +11 -11
- package/lib/dist/workflows/defaults/spec-author.yaml +9 -9
- package/lib/dist/workflows/defaults/spec-fix.yaml +8 -8
- package/lib/dist/workflows/defaults/spec-implement.yaml +38 -23
- package/lib/dist/workflows/defaults/spec-relink.yaml +5 -5
- package/lib/dist/workflows/defaults/spec-verify.yaml +3 -3
- package/lib/dist/workflows/executor.d.ts +7 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +22 -5
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +3 -2
- package/package.json +1 -1
- package/lib/dist/installer/config-writer.d.ts.map +0 -1
- package/lib/dist/installer/config-writer.js.map +0 -1
- package/lib/dist/installer/gemini-commands.d.ts.map +0 -1
- package/lib/dist/installer/gemini-commands.js.map +0 -1
- package/lib/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/lib/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/lib/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/lib/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/lib/dist/ui/assets/index-BzuUWUAE.js +0 -50
- package/lib/dist/ui/assets/index-ezwX2EfG.css +0 -1
|
@@ -140,6 +140,52 @@ const INSTANTIATION_KINDS = new Set([
|
|
|
140
140
|
'object_creation_expression', // java / c#
|
|
141
141
|
'instance_creation_expression', // some grammars
|
|
142
142
|
]);
|
|
143
|
+
/**
|
|
144
|
+
* Languages whose grammar lexes Annex-B HTML-like comments (`<!--`, `-->`),
|
|
145
|
+
* including inside regex literals — the case parseWithLiteralMask repairs.
|
|
146
|
+
*/
|
|
147
|
+
const JS_FAMILY = new Set(['typescript', 'tsx', 'javascript', 'jsx']);
|
|
148
|
+
/**
|
|
149
|
+
* One pre-order walk over a tree: the start offset of every `html_comment`
|
|
150
|
+
* node, and the number of `ERROR` / missing nodes.
|
|
151
|
+
*/
|
|
152
|
+
function scanParseTree(tree) {
|
|
153
|
+
const htmlCommentStarts = [];
|
|
154
|
+
let errorCount = 0;
|
|
155
|
+
const cursor = tree.walk();
|
|
156
|
+
try {
|
|
157
|
+
for (;;) {
|
|
158
|
+
const node = cursor.currentNode;
|
|
159
|
+
if (node.type === 'html_comment')
|
|
160
|
+
htmlCommentStarts.push(node.startIndex);
|
|
161
|
+
else if (node.type === 'ERROR' || node.isMissing)
|
|
162
|
+
errorCount++;
|
|
163
|
+
if (cursor.gotoFirstChild())
|
|
164
|
+
continue;
|
|
165
|
+
while (!cursor.gotoNextSibling()) {
|
|
166
|
+
if (!cursor.gotoParent())
|
|
167
|
+
return { htmlCommentStarts, errorCount };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
cursor.delete();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Declaration kinds whose range, when it fully encloses a parse-error region,
|
|
177
|
+
* means the region's code still produced a declaration (REQ-HTMLLEX-003).
|
|
178
|
+
* Locals (variables, constants, properties) never count: a malformed function
|
|
179
|
+
* whose body still yields local constants must warn.
|
|
180
|
+
*/
|
|
181
|
+
const PARSE_REGION_ENCLOSING_KINDS = new Set([
|
|
182
|
+
'function', 'method', 'class', 'struct', 'interface', 'trait', 'enum',
|
|
183
|
+
'type_alias', 'namespace', 'module', 'component', 'route',
|
|
184
|
+
]);
|
|
185
|
+
/** Number of `<!--` and `-->` occurrences — the bound on mask attempts. */
|
|
186
|
+
function countHtmlCommentDelimiters(source) {
|
|
187
|
+
return (source.match(/<!--|-->/g) ?? []).length;
|
|
188
|
+
}
|
|
143
189
|
/**
|
|
144
190
|
* TreeSitterExtractor - Main extraction class
|
|
145
191
|
*/
|
|
@@ -161,6 +207,69 @@ class TreeSitterExtractor {
|
|
|
161
207
|
this.language = language || (0, grammars_1.detectLanguage)(filePath, source);
|
|
162
208
|
this.extractor = languages_1.EXTRACTORS[this.language] || null;
|
|
163
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Parse `this.source`, repairing the JS-family grammar's habit of lexing
|
|
212
|
+
* `<!--` / `-->` inside regex literals as HTML-like comments, which turns the
|
|
213
|
+
* enclosing declaration into an ERROR node (REQ-HTMLLEX-001).
|
|
214
|
+
*
|
|
215
|
+
* When the first parse contains `html_comment` nodes, each comment's opening
|
|
216
|
+
* delimiter is masked with a same-length string (`<!--` → `<!-_`,
|
|
217
|
+
* `-->` → `-_>`) in a copy of the source and the copy is reparsed. Offsets,
|
|
218
|
+
* rows and columns are unchanged, and node text is always sliced from the
|
|
219
|
+
* original `this.source`. A mask is kept only when the reparse has fewer
|
|
220
|
+
* ERROR nodes, or the same number and fewer `html_comment` nodes (a
|
|
221
|
+
* mis-lexed comment can swallow the rest of a line without any ERROR).
|
|
222
|
+
* A genuine HTML comment in a legacy script makes the reparse worse, so it
|
|
223
|
+
* keeps its meaning. Non-JS languages return the first parse untouched.
|
|
224
|
+
*/
|
|
225
|
+
parseWithLiteralMask(parser) {
|
|
226
|
+
const original = parser.parse(this.source) ?? null;
|
|
227
|
+
if (!original || !JS_FAMILY.has(this.language))
|
|
228
|
+
return original;
|
|
229
|
+
if (!this.source.includes('<!--') && !this.source.includes('-->'))
|
|
230
|
+
return original;
|
|
231
|
+
let best = original;
|
|
232
|
+
let bestScan = scanParseTree(best);
|
|
233
|
+
if (bestScan.htmlCommentStarts.length === 0)
|
|
234
|
+
return original;
|
|
235
|
+
const chars = this.source.split('');
|
|
236
|
+
const tried = new Set();
|
|
237
|
+
let budget = countHtmlCommentDelimiters(this.source);
|
|
238
|
+
let improved = true;
|
|
239
|
+
while (improved && budget > 0) {
|
|
240
|
+
improved = false;
|
|
241
|
+
for (const start of bestScan.htmlCommentStarts) {
|
|
242
|
+
if (tried.has(start) || budget <= 0)
|
|
243
|
+
continue;
|
|
244
|
+
tried.add(start);
|
|
245
|
+
const saved = chars.slice(start, start + 4);
|
|
246
|
+
if (this.source.startsWith('<!--', start))
|
|
247
|
+
chars[start + 3] = '_';
|
|
248
|
+
else if (this.source.startsWith('-->', start))
|
|
249
|
+
chars[start + 1] = '_';
|
|
250
|
+
else
|
|
251
|
+
continue;
|
|
252
|
+
budget--;
|
|
253
|
+
const candidate = parser.parse(chars.join('')) ?? null;
|
|
254
|
+
const scan = candidate ? scanParseTree(candidate) : null;
|
|
255
|
+
if (candidate && scan && (scan.errorCount < bestScan.errorCount ||
|
|
256
|
+
(scan.errorCount === bestScan.errorCount &&
|
|
257
|
+
scan.htmlCommentStarts.length < bestScan.htmlCommentStarts.length))) {
|
|
258
|
+
if (best !== original)
|
|
259
|
+
best.delete();
|
|
260
|
+
best = candidate;
|
|
261
|
+
bestScan = scan;
|
|
262
|
+
improved = true;
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
candidate?.delete();
|
|
266
|
+
chars.splice(start, saved.length, ...saved);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (best !== original)
|
|
270
|
+
original.delete();
|
|
271
|
+
return best;
|
|
272
|
+
}
|
|
164
273
|
/**
|
|
165
274
|
* Parse and extract from the source code
|
|
166
275
|
*/
|
|
@@ -200,7 +309,7 @@ class TreeSitterExtractor {
|
|
|
200
309
|
};
|
|
201
310
|
}
|
|
202
311
|
try {
|
|
203
|
-
this.tree =
|
|
312
|
+
this.tree = this.parseWithLiteralMask(parser);
|
|
204
313
|
if (!this.tree) {
|
|
205
314
|
throw new Error('Parser returned null tree');
|
|
206
315
|
}
|
|
@@ -230,6 +339,7 @@ class TreeSitterExtractor {
|
|
|
230
339
|
if (packageNodeId)
|
|
231
340
|
this.nodeStack.push(packageNodeId);
|
|
232
341
|
this.visitNode(this.tree.rootNode);
|
|
342
|
+
this.reportParseErrorRegions(this.tree.rootNode);
|
|
233
343
|
if (packageNodeId)
|
|
234
344
|
this.nodeStack.pop();
|
|
235
345
|
this.nodeStack.pop();
|
|
@@ -267,6 +377,63 @@ class TreeSitterExtractor {
|
|
|
267
377
|
durationMs: Date.now() - startTime,
|
|
268
378
|
};
|
|
269
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* Report parse-error regions that may have swallowed declarations
|
|
382
|
+
* (REQ-HTMLLEX-003). Collects every outermost `ERROR` node and emits one
|
|
383
|
+
* `warning`-severity `parse_error_region` error for each region that is not
|
|
384
|
+
* fully enclosed by an extracted declaration (function, method, class, …).
|
|
385
|
+
* A region inside an extracted function's body stays silent; a region at
|
|
386
|
+
* program level always warns, even when local constants were extracted from
|
|
387
|
+
* inside it. Only appends to `this.errors` — nodes and edges are untouched,
|
|
388
|
+
* so retrieval output is unchanged. Clean trees cost one `hasError` check.
|
|
389
|
+
*/
|
|
390
|
+
reportParseErrorRegions(root) {
|
|
391
|
+
if (!root.hasError)
|
|
392
|
+
return;
|
|
393
|
+
const regions = [];
|
|
394
|
+
const stack = [root];
|
|
395
|
+
while (stack.length > 0) {
|
|
396
|
+
const node = stack.pop();
|
|
397
|
+
if (node.isError) {
|
|
398
|
+
regions.push({
|
|
399
|
+
startLine: node.startPosition.row + 1,
|
|
400
|
+
startColumn: node.startPosition.column,
|
|
401
|
+
endLine: node.endPosition.row + 1,
|
|
402
|
+
endColumn: node.endPosition.column,
|
|
403
|
+
});
|
|
404
|
+
continue; // outermost only — don't descend into an ERROR node
|
|
405
|
+
}
|
|
406
|
+
for (let i = node.childCount - 1; i >= 0; i--) {
|
|
407
|
+
const child = node.child(i);
|
|
408
|
+
if (child && child.hasError)
|
|
409
|
+
stack.push(child);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (regions.length === 0)
|
|
413
|
+
return;
|
|
414
|
+
const enclosing = this.nodes.filter((n) => PARSE_REGION_ENCLOSING_KINDS.has(n.kind));
|
|
415
|
+
regions.sort((a, b) => a.startLine - b.startLine);
|
|
416
|
+
for (const region of regions) {
|
|
417
|
+
// Position-precise: a stray `}` right after a function's own closing
|
|
418
|
+
// brace sits on the function's last line but outside its range.
|
|
419
|
+
const enclosed = enclosing.some((n) => (n.startLine < region.startLine ||
|
|
420
|
+
(n.startLine === region.startLine && n.startColumn <= region.startColumn)) &&
|
|
421
|
+
(n.endLine > region.endLine ||
|
|
422
|
+
(n.endLine === region.endLine && n.endColumn >= region.endColumn)));
|
|
423
|
+
if (enclosed)
|
|
424
|
+
continue;
|
|
425
|
+
const range = region.startLine === region.endLine
|
|
426
|
+
? `line ${region.startLine}`
|
|
427
|
+
: `lines ${region.startLine}–${region.endLine}`;
|
|
428
|
+
this.errors.push({
|
|
429
|
+
message: `Parse error region at ${range} produced no enclosing declaration; some declarations may be missing`,
|
|
430
|
+
filePath: this.filePath,
|
|
431
|
+
line: region.startLine,
|
|
432
|
+
severity: 'warning',
|
|
433
|
+
code: 'parse_error_region',
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
270
437
|
/**
|
|
271
438
|
* Visit a node and extract information
|
|
272
439
|
*/
|