tackbox 0.1.69 → 0.1.70

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.
Files changed (2) hide show
  1. package/README.md +105 -16
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -457,6 +457,74 @@ event, `dev.py check`, and CI reports until the entry lands or the
457
457
  marker is reverted. Removing a manifest line is free; a marker whose
458
458
  text, scope, or count changes needs its entry updated the same way.
459
459
 
460
+ ## Generated and vendored code
461
+
462
+ Committed code that carries a generated or vendored git attribute is
463
+ excluded from the whole lint - findings there are not fixable in the
464
+ file (they belong in the generator), and a suppression marker cannot
465
+ survive regeneration. tackbox honors exactly three attributes,
466
+ `linguist-generated`, `gitlab-generated`, and `linguist-vendored`,
467
+ read from `.gitattributes` the same way the host (GitHub, GitLab)
468
+ reads them - no exclude surface of tackbox's own. The best fix stays
469
+ organizational: generated code should normally not be committed at
470
+ all; this serves the forced residue.
471
+
472
+ A file is excluded when `git check-attr` reports one of the three as
473
+ set. Semantics by example:
474
+
475
+ ```text
476
+ gen/** linguist-generated
477
+ vendor/** linguist-vendored
478
+ gen/keep.go linguist-generated=false
479
+ ```
480
+
481
+ `gen/**` excludes everything under `gen/`; `vendor/**` the same for
482
+ vendored. Note `dir/**`, not `dir/` - gitattributes patterns, unlike
483
+ gitignore, do not match a trailing-slash directory form. `=false`
484
+ re-includes a single file inside an excluded tree (`gen/keep.go` above
485
+ is linted normally); `-attr` and `!attr` also leave a file in. Only
486
+ `set` / `=true` excludes.
487
+
488
+ The exclusion covers everything: per-file engines, the erclint Go
489
+ package run (a mixed package's excluded file is compiled but its
490
+ findings drop; a compile break still fails loudly), duplication, the
491
+ CodeClimate report, and the marker inventory - an excluded file's
492
+ markers are dead, so a manifest entry addressing one orphans. A lint
493
+ run whose scope touches excluded files prints one summary line:
494
+
495
+ ```text
496
+ excluded by attributes: 12 files in scope (tackbox escapes lists all)
497
+ ```
498
+
499
+ It counts unique excluded files in the current scope (absent at zero),
500
+ so scoped runs are not wallpapered with a global constant;
501
+ `tackbox escapes` lists the full population as `attribute-excluded`
502
+ entries.
503
+
504
+ Because the excluded population is where the lint, the marker
505
+ inventory, and host diff review are all blind, the agent hook makes
506
+ the two ways into it loud:
507
+
508
+ - adding a positive exclusion line (a bare `<attr>` or `<attr>=true`)
509
+ to any `.gitattributes` draws a PreToolUse ask, one joint ask per
510
+ edit listing every added line; removals, `=false`, `-attr`, and
511
+ non-exclusion lines are free;
512
+ - editing (or creating) a file that is effective-excluded draws an
513
+ ask naming the attributes.
514
+
515
+ Generators run through Bash and are unaffected - the boundary is that
516
+ the change stays in the commit/PR diff, and hosts collapse
517
+ excluded-file diffs, so reviewers must expand them.
518
+
519
+ `tackbox doctor` adds an informational `attributes` section (never a
520
+ check, no exit-code effect) naming local conditions that can make a
521
+ run diverge from a clean CI clone - an `info/attributes` or an
522
+ untracked/index-hidden `.gitattributes` carrier mentioning the
523
+ attributes, or a neutralized attribute source override. `tackbox
524
+ escapes --since <rev>` resolves the baseline's attributes as of the
525
+ rev and so needs git >= 2.40 (older git is a named infra error on the
526
+ `--since` path only; the plain listing needs no version bump).
527
+
460
528
  ## Runtime reporting helpers
461
529
 
462
530
  Direct reporting helpers ship per language; their shared runtime behavior -
@@ -483,9 +551,11 @@ Claude Code hook event on stdin and dispatches by `hook_event_name`:
483
551
  nothing, and the block repeats on every event until the tree is
484
552
  consistent. The authoritative gate stays pre-commit / CI.
485
553
  - **PreToolUse** asks for approval before a new `.tackbox/approvals`
486
- line or a new `.tackbox/reporters` line lands; removing one is
487
- free. Editing markers in code draws no Pre ask - the consistency
488
- check owns them.
554
+ line or a new `.tackbox/reporters` line lands, before a positive
555
+ exclusion line is added to any `.gitattributes`, and before an edit
556
+ to an attribute-excluded file (see "Generated and vendored code");
557
+ removing a line is free. Editing markers in code draws no Pre ask -
558
+ the consistency check owns them.
489
559
 
490
560
  Only markers in files an engine would lint participate in the check
491
561
  (D012): a marker in a Go `testdata/` path or a non-lintable fixture
@@ -543,9 +613,11 @@ uvx tackbox@latest escapes --since origin/main --context 5
543
613
 
544
614
  ```json
545
615
  {
546
- "version": 1,
616
+ "version": 2,
547
617
  "since": null,
548
618
  "entries": [
619
+ {"kind": "attribute-excluded", "file": "gen/api.pb.go",
620
+ "attribute": "linguist-generated"},
549
621
  {"kind": "marker", "file": "a/b.py", "line": 12,
550
622
  "text": "no-report: central boundary already captures it",
551
623
  "reason": "central boundary already captures it",
@@ -559,13 +631,19 @@ uvx tackbox@latest escapes --since origin/main --context 5
559
631
  {"kind": "quiet-site", "file": "go/x.go", "line": 9,
560
632
  "text": "report.Quiet(ctx, ...)", "context": ["..."]}
561
633
  ],
562
- "counts": {"marker": 1, "reporter-decl": 1, "notify-site": 1, "quiet-site": 1}
634
+ "counts": {"marker": 1, "reporter-decl": 1, "notify-site": 1,
635
+ "quiet-site": 1, "attribute-excluded": 1}
563
636
  }
564
637
  ```
565
638
 
566
- - `version` is the schema version (`1`); `counts` always carries all four
567
- kinds, even at zero, so consumers see a stable shape.
639
+ - `version` is the schema version (`2`); `counts` always carries all five
640
+ kinds, even at zero, so consumers see a stable shape. Every count is an
641
+ entry count except `attribute-excluded`, which counts unique files.
568
642
  - `since` echoes the `--since` rev, or `null`.
643
+ - `attribute-excluded` entries carry only `kind` / `file` / `attribute` (no
644
+ line or text): the whole file is the bypass, one entry per set attribute
645
+ of the three (`linguist-generated`, `gitlab-generated`,
646
+ `linguist-vendored`). See "Generated and vendored code".
569
647
  - `text` is the trimmed source line; for a marker it runs from the marker
570
648
  keyword to end of line.
571
649
  - `reason` (markers only) is what follows the keyword's colon, trimmed -
@@ -574,14 +652,18 @@ uvx tackbox@latest escapes --since origin/main --context 5
574
652
  (default 3), inclusive of the entry line itself - the window
575
653
  `[line-N, line+N]`, clipped at file edges, each line trimmed of trailing
576
654
  whitespace. It is plain source; the entry line is not marked.
577
- - `entries` are sorted by `(file, line)` for stable output.
655
+ - `entries` are sorted by `(file, kind, kind-subkey)` - the subkey is
656
+ `(line, text)` for the line-bearing kinds and `(attribute,)` for
657
+ `attribute-excluded`.
578
658
 
579
659
  ### Scope and detection
580
660
 
581
661
  The scan covers the same lintable source set the linter would scan (the
582
662
  D012 predicate: extension match plus each engine's path filter, so a Go
583
- `testdata/` file is out), plus the root `.tackbox/reporters` (every
584
- non-empty line is one declaration - the file has no comment syntax).
663
+ `testdata/` file is out) minus the attribute-excluded files, plus the root
664
+ `.tackbox/reporters` (every non-empty line is one declaration - the file has
665
+ no comment syntax). An attribute-excluded file's own markers are dead, so it
666
+ surfaces only as its `attribute-excluded` entries.
585
667
  notify / quiet call sites are detected **textually per language**
586
668
  (`report_quiet` / `notify` in Python, `reportQuiet` / `notify` in the JS
587
669
  family, `.Quiet(` / `.Notify(` in Go, `.quiet(` / `.notify(` in Java),
@@ -592,12 +674,19 @@ this is observability, not a lint.
592
674
  ### `--since <rev>`
593
675
 
594
676
  `--since <rev>` prints only entries **new against `<rev>`**, compared by
595
- content identity `(kind, file, text)` - the same extraction run against
596
- the tree at `<rev>` (via `git ls-tree` + `git show`) subtracted, count
597
- aware, from the current tree's entries. It over-reports on moved code (a
598
- new file path is a new identity) but never silently drops an entry - the
599
- conservative direction for a review aid. A bad rev is the one infra error:
600
- one stderr line, exit 1.
677
+ content identity (`(kind, file, text)`, or `(kind, file, attribute)` for
678
+ attribute-excluded) - the same extraction run against the tree at `<rev>`
679
+ (via `git ls-tree` + `git show`) subtracted, count aware, from the current
680
+ tree's entries. The baseline is attribute-aware: it resolves the attributes
681
+ as of `<rev>` (via the seam's `git check-attr --source`), so an attribute
682
+ added since the rev reports its newly-excluded files, a removed one
683
+ re-activates its markers as new (never a silent subtraction), and an
684
+ unchanged one adds no noise. Because `--source` needs git >= 2.40, an older
685
+ git is a named infra error on the `--since` path only (the plain listing
686
+ needs no version bump). It over-reports on moved code (a new file path is a
687
+ new identity) but never silently drops an entry - the conservative direction
688
+ for a review aid. A bad rev is the other infra error: one stderr line,
689
+ exit 1.
601
690
 
602
691
  ## Layout
603
692
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tackbox",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "description": "ESLint and Markdown lint plugins plus direct error-reporting helpers for JavaScript and TypeScript.",
5
5
  "license": "MIT",
6
6
  "main": "./js/eslint-plugin.js",