Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ category: "tech-debt"
source: "user-observation"
found_during: "abcd-run-design"
found_at: "internal/core/memory/lint.go"
resolution: "relocated memory-lint report dir + scanner skip fragments from .abcd/logbook to .abcd/.work.local/logs; source-grep detector armed; plugin doc updated. Record-lint markdown ban-arming deferred (needs research-note reconciliation)"
---

Relocate memory-lint logbook output and scanner skip-paths from .abcd/logbook/ (a retired location per iss-36) to .abcd/.work.local/logs/, the gitignored runtime-artefact tier. Maintainer adjudication of iss-56 (2026-07-12): runtime artefacts belong in .work.local/logs/, not a tracked dir. Sites: internal/core/memory/lint.go writes .abcd/logbook/memory/lint dirs; internal/adapter/scanner/scanner.go defaultSkipFragments references .abcd/logbook/pii-scan/ and audit-history/. Fix both plus tests; once the binary no longer writes there the .abcd/logbook retired-location ban (iss-36/iss-56) can be armed. Actionable fix behind iss-56 adjudication.
2 changes: 1 addition & 1 deletion commands/abcd/memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ abcd memory lint --json
```

It rebuilds the regenerable `.coverage_index.json` and writes a report under
`.abcd/logbook/memory/lint-<ts>/`. Summarise `summary.blockers` /
`.abcd/.work.local/logs/memory/lint-<ts>/`. Summarise `summary.blockers` /
`summary.warnings` / `summary.infos` and each finding's `code` and `message`.
Blockers exit nonzero; warn-only exits 0.

Expand Down
45 changes: 45 additions & 0 deletions internal/adapter/scanner/retired_location_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package scanner

import (
"os"
"path/filepath"
"strings"
"testing"
)

// TestNoRetiredLogbookLocationInSource is the iss-73 detector: `.abcd/logbook/`
// is a retired runtime-output location (iss-36/iss-56). A 2026-07-12 maintainer
// adjudication placed runtime artefacts in the gitignored `.abcd/.work.local/logs/`
// tier instead, so no non-test Go source under internal/ may name the retired
// `logbook` location — not memory's lint-report dir, not the scanner's skip
// fragments. It walks internal/ from this package (internal/adapter/scanner).
func TestNoRetiredLogbookLocationInSource(t *testing.T) {
internalRoot := filepath.Join("..", "..") // internal/adapter/scanner -> internal/
var offenders []string
err := filepath.WalkDir(internalRoot, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
if !strings.HasSuffix(d.Name(), ".go") || strings.HasSuffix(d.Name(), "_test.go") {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
if strings.Contains(string(data), "logbook") {
offenders = append(offenders, path)
}
return nil
})
if err != nil {
t.Fatalf("walk internal/: %v", err)
}
if len(offenders) > 0 {
t.Fatalf("retired '.abcd/logbook' location named in Go source (relocate to .abcd/.work.local/logs/):\n %s",
strings.Join(offenders, "\n "))
}
}
2 changes: 1 addition & 1 deletion internal/adapter/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var (
".sqlite", ".db", ".lock",
}
defaultSkipFilenames = []string{".DS_Store", "Thumbs.db", ".gitignore"}
defaultSkipFragments = []string{".abcd/logbook/pii-scan/", ".abcd/logbook/audit-history/"}
defaultSkipFragments = []string{".abcd/.work.local/logs/pii-scan/", ".abcd/.work.local/logs/audit-history/"}
repoConfigRelPath = filepath.Join(".abcd", "config", "pii.json")
)

Expand Down
14 changes: 8 additions & 6 deletions internal/core/memory/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// lint.go — the `abcd memory lint` verb (fn-39): a full-store curator
// health-check. Page-local checks (MS001/MS002/ML001/MQ001/MQ003) per typed
// page, plus a corpus pass (MQ002 + per-source MQ003) that rebuilds the
// regenerable .coverage_index.json. Writes ONE logbook report; mutates no
// regenerable .coverage_index.json. Writes ONE run-log report; mutates no
// memory-store state. Exit contract: blocker -> 1; warn/info/clean -> 0.

// Finding is a single memory-lint finding.
Expand Down Expand Up @@ -388,7 +388,7 @@ func runMemoryCoverageLint(repoRoot string) ([]Finding, map[string]any, error) {
// Lint orchestration
// ---------------------------------------------------------------------------

// Lint runs the full-store curator health-check and writes one logbook report.
// Lint runs the full-store curator health-check and writes one run-log report.
// Mutates no memory-store state (only the regenerable coverage index + report).
func Lint(req LintRequest) (LintResult, error) {
root := req.RepoRoot
Expand Down Expand Up @@ -484,18 +484,20 @@ func Lint(req LintRequest) (LintResult, error) {

func lintReportDir(repoRoot string, now time.Time) (string, error) {
ts := now.Format("20060102T150405.000000Z")
logbook := filepath.Join(repoRoot, ".abcd", "logbook", "memory")
base := filepath.Join(logbook, "lint-"+ts)
// Runtime artefacts live in the gitignored .abcd/.work.local/logs/ tier, not
// the retired runtime location (iss-36/iss-56 adjudication, iss-73).
logs := filepath.Join(repoRoot, ".abcd", ".work.local", "logs", "memory")
base := filepath.Join(logs, "lint-"+ts)
if _, err := os.Stat(base); os.IsNotExist(err) {
return base, nil
}
for n := 1; n < 1000; n++ {
candidate := filepath.Join(logbook, fmt.Sprintf("lint-%s-%03d", ts, n))
candidate := filepath.Join(logs, fmt.Sprintf("lint-%s-%03d", ts, n))
if _, err := os.Stat(candidate); os.IsNotExist(err) {
return candidate, nil
}
}
return "", fmt.Errorf("could not allocate a unique lint logbook dir for %s", ts)
return "", fmt.Errorf("could not allocate a unique lint run-log dir for %s", ts)
}

func findingsToMaps(findings []Finding) []any {
Expand Down
Loading