Skip to content

Simplify project comments and enforce banned words - #908

Merged
taras merged 4 commits into
mainfrom
agent/issue-907-core-comment-cleanup
Oct 14, 2026
Merged

taras merged 4 commits into
mainfrom
agent/issue-907-core-comment-cleanup

Conversation

@taras

@taras taras commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Why

Source comments had accumulated repeated architecture explanations and narration already clear from adjacent code. Architecture prose and JSDoc also used “claim” for several different actions. This simplifies those explanations and enforces one shared banned-words list so new prose uses concrete terms.

Closes #907

What changes

Shared rationale is stated once, mechanical narration is removed, and oversized local explanations are shortened. Stale synchronous-read, default-plugin and Issue boundary wording now describes existing behavior.

The comment cleanup covers 367 source files across the major packages, scripts and site, plus scoped terminology edits in architecture.md. Lint tooling adds the enforcement described below. Distinct member contracts, evaluation/caller scope, cancellation and resource ownership, validation/failure order, persistence/replay constraints, specification references and tool/license/provenance annotations remain intact.

Banned-words enforcement

scripts/banned-words.js is the single editable list of words and explicit forms. AGENTS.md links it with generic writing guidance.

deno task lint enables local/no-banned-jsdoc-words for JSDoc and runs the architecture prose checker using the same matcher. Matching is case-insensitive at whole-word boundaries; diagnostics include the word and its location. Inline/fenced/indented code, JSDoc annotation identifiers and types, and literal link targets remain code references. There is no automatic replacement.

Site and smoke-test JSDoc run through a prose-only Oxlint profile, preserving their existing code-style ownership. Other source comments, other Markdown and vendored/generated material are outside this enforcement.

Review guide

Start with ExecutionInstallation in packages/core/src/execute.ts for the shared capture rationale and retained member contracts. Then review the shortened module headers and lifecycle explanations across packages, followed by redundant test and local implementation narration. Every changed comment received contextual review.

The inventory covers 1,709 tracked paths: 378 changed, 25 reviewed and kept, 792 scanned with no candidate selected, 85 with no comments, and 429 excluded. The project JSDoc and architecture checks pass with no remaining banned-word errors. Exact API and path references such as claim(invocation), claim(carrier) and claims/<n> remain accurate. Search-only triage is distinct from manual contextual review; this does not claim every retained comment was manually reread.

What must stay true

The existing product-source edits remain comment-only; functional code additions implement lint enforcement and its regression tests. Parser-produced non-comment tokens, comment-free JavaScript and protected annotations compare identically to base 9c4f4f9a66e25c1c396c0e65c72d35dff722c5ec in all 367 source files. The terminology follow-up separately verifies all non-JSDoc comments unchanged across its 290 source files against 90659d220c8708bafa4af5130628b42b0b65e3cf. Architecture edits reconstruct exactly from reviewed contextual replacements, and its fenced examples and inline code remain unchanged. Committed file bytes match the accepted editorial snapshots.

The additional configuration edits wire lint and agent guidance. Vendored/generated material, dependencies, executable Markdown and other guides remain intact. Coverage/ownership and boundary checks confirm this scope and unchanged file modes. Five new files supply the list, matcher, JSDoc rule, architecture check and prose-only configuration. The test corpus file set remains unchanged.

How to verify it

Focused policy tests pass all 20 steps, including real configured Oxlint failures, CRLF locations, literal-code controls, isolated list extension through both consumers and lint wiring:

deno task test scripts/tests/oxlint-policy.test.ts
deno task lint

The complete lint task passes, including architecture prose, both JSDoc scopes, formatting and dead-code checks. The source-comment cohort retains identical non-comment tokens and emitted JavaScript using TypeScript 5.9.3. Its exact paths can be selected from the reviewed cleanup commit, so the helper does not treat new lint code as a comment-only edit:

base=9c4f4f9a66e25c1c396c0e65c72d35dff722c5ec
git diff --name-only "$base" 2bc1f2e4636bdd6333e4cbe686fc955258ca1e9c -- '*.ts' '*.tsx' '*.mts' '*.cts' '*.js' '*.jsx' '*.mjs' '*.cjs' > /tmp/xmd-comment-files.txt
# Save the helper below as /tmp/xmd-verify-comments.cjs.
node /tmp/xmd-verify-comments.cjs $(cat /tmp/xmd-comment-files.txt)
node_modules/.bin/oxlint -c .oxlintrc.json $(cat /tmp/xmd-comment-files.txt)
rg -v '^site/' /tmp/xmd-comment-files.txt > /tmp/xmd-oxfmt-files.txt
node_modules/.bin/oxfmt --check $(cat /tmp/xmd-oxfmt-files.txt)
deno fmt --check site/components/Prose.tsx
git diff --check "$base" HEAD

The helper compares parsed token kinds/text, comment-free transpilation and full protected comment contents against the exact base. It protects actual JSDoc tags, compiler/linter directives, pure/source-map markers and license/generated/provenance notices. Boundary checks additionally confirmed all 1,709 tracked paths have dispositions, changed paths match the 378 reviewed entries, and excluded/dependency inputs are unchanged. The changed Markdown is limited to architecture wording and generic banned-words guidance in AGENTS.md.

Portable comment-equivalence helper (temporary verification artifact)
const fs = require('node:fs');
const cp = require('node:child_process');
const path = require('node:path');
const assert = require('node:assert/strict');
const root = process.cwd();
const ts = require(path.join(root, 'node_modules/typescript'));
const base = '9c4f4f9a66e25c1c396c0e65c72d35dff722c5ec';
const files = process.argv.slice(2);
assert.ok(files.length, 'Pass explicit repository-relative source paths');
function parsedSource(source, fileName) {
  const extension = path.extname(fileName).toLowerCase();
  const kind = extension === '.tsx' ? ts.ScriptKind.TSX : extension === '.jsx' ? ts.ScriptKind.JSX : ['.js', '.mjs', '.cjs'].includes(extension) ? ts.ScriptKind.JS : ts.ScriptKind.TS;
  assert.ok(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'].includes(extension), 'Unsupported source format: ' + fileName);
  const parsed = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, kind);
  assert.equal(parsed.parseDiagnostics.length, 0, fileName + ' source parse diagnostics');
  return parsed;
}
function tokens(source, fileName) {
  const parsed = parsedSource(source, fileName);
  const result = [];
  function visit(node) {
    if (node.kind >= ts.SyntaxKind.FirstJSDocNode && node.kind <= ts.SyntaxKind.LastJSDocNode) { return; }
    const children = node.getChildren(parsed);
    if (children.length === 0 && node.kind <= ts.SyntaxKind.LastToken && node.kind !== ts.SyntaxKind.EndOfFileToken) {
      result.push([node.kind, node.getText(parsed)]);
    } else {
      children.forEach(visit);
    }
  }
  visit(parsed);
  return result;
}
function comments(source, fileName) {
  const parsed = parsedSource(source, fileName);
  const ranges = new Map();
  function add(items) {
    for (const range of items || []) { ranges.set(range.pos, source.slice(range.pos, range.end)); }
  }
  function visit(node) {
    add(ts.getLeadingCommentRanges(source, node.getFullStart()));
    add(ts.getTrailingCommentRanges(source, node.end));
    node.getChildren(parsed).forEach(visit);
  }
  visit(parsed);
  return [...ranges].sort((a, b) => a[0] - b[0]).map(([pos, text]) => ({ pos, text }));
}
function emitted(source, fileName) {
  if (/\.d\.[cm]?ts$/.test(fileName)) { return null; }
  const result = ts.transpileModule(source, {
    fileName,
    compilerOptions: { target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.ESNext, jsx: ts.JsxEmit.Preserve, allowJs: true, removeComments: true, sourceMap: false },
    reportDiagnostics: true,
  });
  assert.equal(result.diagnostics.length, 0, fileName + ' transpilation diagnostics');
  return result.outputText;
}
function protectedComments(source, fileName) {
  return comments(source, fileName).map(item => item.text).filter(text => /(?:^|\n)\s*(?:\/\/|\/\*\*?|\*)\s*@[A-Za-z][\w-]*/.test(text) || /(?:deno-lint-|oxlint-|oxfmt-|eslint-|prettier-|@ts-(?:ignore|expect-error|check|nocheck)|<reference\s|[#@]\s*source(?:Mapping)?URL\s*=|biome-ignore|jshint|jscs|tslint:|webpack|vite-ignore|copyright|SPDX|\blicen[cs]e\b|licensed under|@generated|auto-generated|automatically generated|generated by|generated file|file (?:is|was) generated|DO NOT EDIT|vendored from|source:\s*https?:|istanbul|c8 ignore|v8 ignore|__PURE__|__NO_SIDE_EFFECTS__)/i.test(text));
}
for (const file of files) {
  const before = cp.execFileSync('git', ['show', base + ':' + file], { cwd: root, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
  const after = fs.readFileSync(path.join(root, file), 'utf8');
  const beforeTokens = tokens(before, file);
  assert.deepEqual(tokens(after, file), beforeTokens, file + ' non-comment tokens');
  assert.equal(emitted(after, file), emitted(before, file), file + ' emitted JavaScript');
  assert.deepEqual(protectedComments(after, file), protectedComments(before, file), file + ' tool/license/provenance annotations');
  console.log('PASS ' + file + ': ' + beforeTokens.length + ' identical non-comment tokens; ' + (/\.d\.[cm]?ts$/.test(file) ? 'declaration-only (no emit)' : 'identical comment-free JavaScript') + '; ' + protectedComments(after, file).length + ' unchanged protected annotations');
}
console.log('TypeScript ' + ts.version + '; base ' + base + '; files ' + files.length);

Risks and limitations

Token and emit equality establish unchanged code in the comment-cleanup cohort; focused regressions cover the added lint behavior. Manual contextual review checks that consequential prose survives. Neither proves every retained comment is correct. Existing lint warnings remain; oxlint reports no errors and formatting passes. Focused lint-policy regressions cover the enforcement; the product runtime suite remains with CI. CI was not inspected during this focused feedback pass.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • The description matches the final diff and focused verification results.

@taras taras changed the title Simplify source comments across the project Simplify project comments and architecture wording Oct 14, 2026
@taras taras changed the title Simplify project comments and architecture wording Simplify project comments and enforce banned words Oct 14, 2026
@taras
taras marked this pull request as ready for review October 14, 2026 12:00
@taras
taras merged commit a032034 into main Oct 14, 2026
43 of 44 checks passed
@taras
taras deleted the agent/issue-907-core-comment-cleanup branch October 14, 2026 12:04
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.

Reduce repetition in project source comments

1 participant