Skip to content

TODO #2

Closed
Closed

Description

@rogeralsing

User report of this issue


Last updated: 2026-01-22

Bugs

Docs

Features

Tests


Investigation

Delivery strictness: full - the complete outcome crosses CLI control flow, build-time release metadata, strategy-specific persisted filenames, documentation, and regression tests, and the repository's canonical quality-evidence producer is currently unavailable.

Current Evidence

  • The clean task worktree is at c700991 (origin/main, tag v0.6.0).
  • go run ./cmd/quickdup -h shows the already-correct -top wording (blended rank) and the replacement -min-rank wording (score + complexity); there is no remaining -min-score flag to repair.
  • go run ./cmd/quickdup --version exits with flag provided but not defined: -version. No version symbol/resolver exists in the current cmd/quickdup package.
  • .goreleaser.yaml currently uses only -s -w; it does not inject a release tag into main.version.
  • Runtime paths are strategy-specific: <strategy>-results.json in cmd/quickdup/main.go, <strategy>-ignore.json in pkg/quickdup/filter.go, and <strategy>-cache.gob in pkg/quickdup/cache.go. Cache load/save deliberately supports only word-indent. README still names generic results.json, cache.gob, and ignore.json in its explanatory sections and does not explain the exact score formula.
  • Current tests contain only limited score assertions and no focused ignore parsing or cache/ignore filename coverage. Historical implementation commits exist on unmerged branches, but they target the pre-pkg/quickdup layout and must be ported rather than cherry-picked.
  • Semantic source evidence confirms cmd/quickdup.main calls pkg/quickdup.LoadIgnoredHashes, and both indent strategies reach the shared scoreIndentShape implementation.

Blast Radius

  • cmd/quickdup/main.go - preserve the corrected rank help, add early --version handling, and make -no-cache help explicit about the word-indent scope.
  • cmd/quickdup/version.go - new main-package version value and deterministic resolution for release, module-build, VCS-revision, and development builds.
  • cmd/quickdup/version_test.go - focused version-resolution regression coverage.
  • .goreleaser.yaml - inject the release tag into the exact main.version symbol while preserving strip flags.
  • README.md - align score/rank semantics, strategy-specific result/cache/ignore filenames, and cache scope with current source.
  • pkg/quickdup/filter.go - make ignore-hash parsing explicit and testable if needed to preserve documented raw, bracketed CLI, and 0x forms and a safe empty result for missing/invalid files.
  • pkg/quickdup/filter_test.go - new ignore file creation, filename, valid-variant, and invalid-input coverage.
  • pkg/quickdup/strategy_score_test.go - new focused scoring coverage adapted to the shared strategy implementations.
  • pkg/quickdup/cache_test.go - new strategy-specific filename and word-indent-only cache coverage carried forward from the issue comment.

Dependencies

  • fk1 - repository canonical quality evidence is unavailable because .faktorial/main-verify.json and declared producers are missing; implementation can be prepared, but the required final run-quality gate cannot complete until that machine-owned repair lands.

User Stories

Story 1: As a QuickDup CLI operator, I want accurate help, version output, and documented output-state paths, so that I can invoke the tool and manage its generated files without guessing.

Story 2: As a QuickDup release maintainer, I want GoReleaser binaries to report their release tag and the behavior contract to be regression-tested, so that published artifacts are identifiable and completed maintenance work does not silently regress.

Approach

  1. Keep the current -min-rank and -top behavior; do not reintroduce obsolete -min-score. Add a version flag that returns before scan setup or timeout behavior. Put resolution in a small cmd/quickdup/version.go surface with dev as the source default, optional Go build-info/VCS fallback, and an ldflags-overridable main.version.
  2. Update GoReleaser ldflags to retain -s -w and add -X main.version={{.Tag}}. Exercise the resolver independently so local/development and injected release identities remain deterministic.
  3. Treat current production code as the documentation source of truth. Document the indent-strategy score as the effective unique-word count after imbalance penalty, multiplied by max(2*similarity-1, 0)^3, plus the integer pattern-length bonus; state separately that rank adds positive indentation complexity. Document <strategy>-results.json, <strategy>-ignore.json, and that only word-indent reads/writes <strategy>-cache.gob.
  4. Port the intended tests into the current package boundaries. Cover word-only, word-indent, normalized-indent, and inlineable scoring; missing/invalid and raw/bracketed/0x ignore hashes; strategy-specific ignore/cache paths; and the non-cacheable strategies. Avoid copying old concrete entry layouts that were removed by the library split.
  5. After fk1 restores repository-owned quality evidence, commit the coherent change and request Faktorial's canonical run-quality verification. Do not substitute agent-run unit tests for that gate.

Risks

  • The historical branches modify the old monolithic cmd/quickdup package; cherry-picking them would undo or conflict with the current library extraction.
  • GoReleaser injection silently fails if the symbol path or variable name differs from main.version; version tests alone do not prove the release YAML wiring.
  • The default strategy is normalized-indent, while caching currently exists only for word-indent; broad cache wording would remain misleading even if the filename were corrected.
  • Score tests can become implementation snapshots. Assert the documented behavior at meaningful boundary cases while preserving strategy-specific semantics.
  • Tests touching package globals such as ActiveStrategy, CommentPrefix, or build-info hooks must restore state and must not use unsafe parallel execution.

Additional quality gates

  • Canonical quality evidence - Do not advance to review until fk1 restores declared repository producers and Faktorial accepts complete build/test evidence from run-quality.
Requested behavior Risk lane Lane evidence Required proof or judgment Buyer consequence if missing Stop or downgrade trigger
Restore the complete issue #2 CLI, release, docs, and regression contract full Current main rejects --version, release ldflags omit the version, documentation contradicts persisted paths, and canonical evidence configuration is missing Accepted repository run-quality evidence after fk1, plus source/config review of the version injection and documentation contract Users can receive unidentifiable releases, misleading file guidance, or silently regressed parsing/scoring behavior Stop before review while fk1 is unresolved or evidence is missing/invalid; return to build on any behavior, test, or config mismatch

Recommended Labels

  • bug
  • documentation
  • enhancement

Acceptance Criteria (Refined)

  • AC-1: CLI help continues to describe -top as ranking by blended rank and -min-rank as the score-plus-complexity threshold; the obsolete -min-score flag is not reintroduced.
  • AC-2: quickdup --version prints exactly one quickdup <identity> line and exits successfully before scanning, creating .quickdup state, or starting timeout work.
  • AC-3: Development/module builds have a deterministic non-empty fallback identity, and a build with -X main.version=vX.Y.Z reports that injected identity.
  • AC-4: GoReleaser preserves its existing stripping flags and injects {{.Tag}} into the same main.version symbol consumed by the CLI.
  • AC-5: README accurately describes the current scoring curve and imbalance/length terms, distinguishes score from blended rank, and matches the current 0.75 similarity default.
  • AC-6: README and CLI help identify <strategy>-results.json, <strategy>-ignore.json, and word-indent-cache.gob behavior accurately, without implying that the default normalized-indent strategy is cached.
  • AC-7: Focused tests cover scoring for all current strategies and ignore parsing/file creation for raw, bracketed, 0x, invalid, and missing inputs using the current pkg/quickdup APIs.
  • AC-8: Focused tests cover strategy-specific cache/ignore filenames and prove that cache persistence is skipped for non-word-indent strategies.
  • AC-9: After fk1 completes, the committed change receives accepted canonical run-quality build/test evidence before review.

Activity

  1. rogeralsing commented on Jan 22, 2026

    @rogeralsing
    ContributorAuthor

    Update: PR #5 covers the README filename alignment and now includes unit tests for strategy-specific cache/ignore filenames.

  2. added
    bugSomething isn't working
    documentationImprovements or additions to documentation
    enhancementNew feature or request
    on Jul 16, 2026
  3. faktorial-ai commented on Jul 16, 2026

    @faktorial-ai
    Contributor

    Build Update

    Committed 9392977 (Restore QuickDup CLI maintenance contract).

    What changed

    • Added --version handling before scan globals, timeout work, or filesystem state, with exact quickdup <identity> output and deterministic injected, module, VCS, and development identities in cmd/quickdup/version.go.
    • Preserved GoReleaser's -s -w flags and added -X main.version={{.Tag}} against the symbol consumed by the CLI.
    • Made ignore parsing accept raw, bracketed, and 0x hexadecimal forms, reject malformed values, and return a safe empty map for missing or invalid files. Runtime output now names the strategy-specific ignore file.
    • Aligned help and README with the 0.75 similarity default, exact score/complexity/rank behavior, <strategy>-results.json, <strategy>-ignore.json, and word-indent-only word-indent-cache.gob. The obsolete -min-score flag remains absent.
    • Added focused current-package regression tests for version resolution/output, all four scoring strategies, ignore creation/parsing/path behavior, the word-indent cache path, and cache skipping for every non-cacheable strategy.

    Evidence and verification

    • Static source-order review confirmed the version return occurs immediately after flag.Parse and before quickdup.Debug or timeout setup.
    • Static config review confirmed .goreleaser.yaml contains -s -w -X main.version={{.Tag}}; documentation scans found all canonical filenames and no -min-score occurrence.
    • git diff --cached --check passed before commit; the post-commit worktree was clean and one commit ahead of origin/main.
    • No tests, builds, typechecks, or canonical quality commands were run in this agent session. Faktorial run-quality is requested for the committed branch.
    • The optional cached GET /api/quickdup review signal returned HTTP 503; feedback was recorded for task gh2. This did not block the source/config proofs or canonical handoff.

    Durable artifacts and runtime notes

    No ADR or prevention rule was required because this restores an existing CLI contract without a new architecture or policy decision. No Faktorial runtime notes or compliance-specific artifacts were present; no generated assets were created.

    Material skills

    Skill: golang-cli
    Why used: Preserve the existing standard-library flag CLI while adding early version output and linker-injected release identity.
    Artifact: cmd/quickdup/version.go, cmd/quickdup/main.go, .goreleaser.yaml
    Outcome: applied
    Verification/follow-up: Faktorial run-quality must verify the committed binary/test contract.

    Skill: golang-testing
    Why used: Shape focused regressions as named behavioral cases against the current package split without unsafe parallel global mutation.
    Artifact: cmd/quickdup/version_test.go, pkg/quickdup/filter_test.go, pkg/quickdup/cache_test.go, pkg/quickdup/strategy_score_test.go
    Outcome: applied
    Verification/follow-up: Tests are intentionally delegated to Faktorial's canonical gate.

    Skill: golang-documentation
    Why used: Keep README and CLI help concise and source-accurate for scoring, rank, persisted filenames, and cache scope.
    Artifact: README.md, cmd/quickdup/main.go, cmd/quickdup/output.go
    Outcome: applied
    Verification/follow-up: Review should compare the prose and help strings with the current strategy/cache implementations.

  4. faktorial-ai commented on Jul 16, 2026

    @faktorial-ai
    Contributor

    Build Update

    Focused verification repair

    • The prior gate failed before executing any quality command because .faktorial/main-verify.json was absent.
    • Checked later work before editing: task fk1 is complete and its commit d6310cd received accepted canonical evidence (1/1 commands passed) for the repository-owned adapter.
    • Integrated that exact verified adapter unchanged as commit 5fda452 on top of the original gh2 implementation commit 9392977. The adapter declares main-verify.v2, runs the repository-native Go evidence producer, emits one required test-results.v1 envelope, and includes focused adapter conformance coverage.

    Static evidence

    • Custom static contract validation passed: the JSON schema version, declared command, producer identity, payload schema, required flag, implementation constants, and tracked conformance file all agree.
    • python3 -m json.tool .faktorial/main-verify.json passed.
    • git diff --check origin/main...HEAD passed.
    • The committed worktree was clean and HEAD was one commit ahead of origin/agent-go/task-gh2.
    • No tests, builds, typechecks, or canonical quality commands were run in this agent session; Faktorial owns their execution after this handoff.

    Durable artifacts and runtime notes

    The repository quality adapter is the required durable verification artifact. No ADR or prevention rule was added because the adapter implements the already-established Faktorial evidence contract and was independently delivered and accepted by fk1. No Faktorial runtime notes or compliance-specific context were present, and no generated assets were created.

    Material skills

    Skill: golang-continuous-integration
    Why used: Diagnose the missing repository quality gate and reuse the repository-owned, already-verified evidence producer instead of creating a competing pipeline.
    Artifact: .faktorial/main-verify.json, scripts/quality_evidence.py, scripts/test_quality_evidence.py
    Outcome: applied
    Verification/follow-up: Faktorial run-quality must execute the committed adapter and review the complete gh2 change.

  5. faktorial-ai commented on Jul 16, 2026

    @faktorial-ai
    Contributor

    Build Update

    Focused verification repair

    • The prior canonical gate reached the Go tests and failed only TestWordIndentCacheUsesStrategySpecificFile: LoadCache() returned nil after SaveCache().
    • Root cause was production code, not test isolation: the library split changed WordIndentEntry to embed the unexported indentEntry. encoding/gob therefore had no serializable fields for that value; SaveCache ignored the encode error and left an unreadable cache file.
    • Committed 4ee1539 (Fix word-indent cache serialization).

    What changed

    • Added native GobEncode/GobDecode methods backed by a private wire struct, preserving the existing exported FileCache/CachedFile API and keeping indentEntry internal.
    • Decoding now rebuilds entries through newIndentEntry, restoring the derived hash bytes that pattern detection consumes.
    • Bumped the cache format to version 2 so pre-repair cache data is treated as stale.
    • Strengthened the existing cache regression to assert all persisted fields and the reconstructed hash bytes, in addition to the strategy-specific filename.

    Static evidence and verification

    • Source inspection proved the mismatch between CachedFile.Entries []WordIndentEntry and the unexported embedded indentEntry; pre-split history showed the entry previously exposed serializable fields directly.
    • Static contract scans confirmed cache version 2, both gob methods, decode through newIndentEntry, and the derived-hash regression assertion.
    • gofmt and git diff --check passed; the post-commit worktree was clean and HEAD was 4ee1539, one commit ahead of origin/agent-go/task-gh2.
    • No tests, builds, typechecks, or canonical quality commands were run in this agent session. Faktorial run-quality is requested for the committed branch.

    Durable artifacts and runtime notes

    No ADR, prevention rule, compliance artifact, generated asset, or runtime note was required: this is a backward-incompatible cache-format repair for derived local state, explicitly invalidated by the cache version. The committed repository quality adapter remains the durable verification artifact.

    Material skills

    Skill: golang-troubleshooting
    Why used: Trace the single deterministic verifier failure through cache save/load and the library-split type history.
    Artifact: pkg/quickdup/cache.go
    Outcome: applied
    Verification/follow-up: Faktorial run-quality must execute the cache regression and full repository evidence.

    Skill: golang-safety
    Why used: Restore derived hash state during decode while keeping the internal entry representation encapsulated.
    Artifact: pkg/quickdup/cache.go
    Outcome: applied
    Verification/follow-up: Canonical tests must confirm loaded entries retain behavior, not only persisted display fields.

    Skill: golang-testing
    Why used: Strengthen the existing behavioral regression around the complete cache round trip without adding a parallel or implementation-only test surface.
    Artifact: pkg/quickdup/cache_test.go
    Outcome: applied
    Verification/follow-up: Test execution is intentionally delegated to Faktorial's canonical gate.

  6. faktorial-ai commented on Jul 16, 2026

    @faktorial-ai
    Contributor

    Review Cache

    {
      "version": 1,
      "task_id": "gh2",
      "pr": 12,
      "base_ref": "origin/main",
      "review_commit": "4ee1539388ed827c5ff415cea26735040d29c2c7",
      "entries": [
        {
          "path": ".faktorial/main-verify.json",
          "status": "ok",
          "blob": "8a76d31db6b3f4f566f87be97451e28c5fc65b93",
          "diff": "1164eee191ed74584c4c6cfe02bbc53c9065f17cb2f0cead4cd8a74e9503b57f",
          "checked": [
            "evidence"
          ],
          "note": "Declares the accepted Go evidence producer and required schema."
        },
        {
          "path": ".gitignore",
          "status": "ok",
          "blob": "045fc62b66b8b64cf51bd2f920f7e84271495507",
          "diff": "90570bfd4f6b5c5938791d6428e043dc95d6f7e7141c3d8b32ae0e0dd217e59c",
          "checked": [
            "scope"
          ],
          "note": "Ignores Python bytecode generated by the evidence tooling."
        },
        {
          "path": ".goreleaser.yaml",
          "status": "ok",
          "blob": "02eff4655676e1321089cb7b757dbbc65212df0c",
          "diff": "ef70de7c6545d88c97caddcbe8ebbfea8345d1f1bd58e84d5fa6cba6425f434d",
          "checked": [
            "release"
          ],
          "note": "Preserves -s -w and injects the tag into main.version."
        },
        {
          "path": "README.md",
          "status": "ok",
          "blob": "812f55979904fb2a5de5dcbe5aeaa5e2723790bd",
          "diff": "9d587073dbec9f5d96432e3f10ff81b7e71a0703e1f04cf058a51f700bcc07fd",
          "checked": [
            "docs"
          ],
          "note": "Matches scoring, rank, defaults, strategy filenames, and cache scope."
        },
        {
          "path": "cmd/quickdup/main.go",
          "status": "ok",
          "blob": "37b8cfca2832d376133aa3995ef09a53ff309e58",
          "diff": "b348b742f224d1748d82d8bb715acdba025bc5284305c4e0bca09127ba0cbfd4",
          "checked": [
            "cli",
            "help"
          ],
          "note": "Version exits immediately after parsing and help retains the required rank wording."
        },
        {
          "path": "cmd/quickdup/output.go",
          "status": "ok",
          "blob": "3dbc6ce31ef472c22556e23a38387edc6b13c0e8",
          "diff": "d11ca0445fb6ba85fbe97456a148a6a18d6104e8db3e1ec245fa36a50f08fcff",
          "checked": [
            "paths"
          ],
          "note": "Reports the strategy-specific ignore filename."
        },
        {
          "path": "cmd/quickdup/version.go",
          "status": "ok",
          "blob": "4448ba8170b55bda6b2ee0dffb6e9f0b31e680a8",
          "diff": "7342882167d27b0ce1f7030d6fad65ef225bda0e53a231cb507e435d15fe4924",
          "checked": [
            "version"
          ],
          "note": "Provides injected, module, VCS, and deterministic development identities."
        },
        {
          "path": "cmd/quickdup/version_test.go",
          "status": "ok",
          "blob": "9c36bcf7bc4c7996f8461e2f005a60ba75f130eb",
          "diff": "5159c2775056adeff8deb6918f6d3959fff5f9f846e830498e5a57d751e2e9a6",
          "checked": [
            "tests"
          ],
          "note": "Covers identity precedence, fallbacks, restoration, and exact one-line output."
        },
        {
          "path": "pkg/quickdup/cache.go",
          "status": "ok",
          "blob": "233a1c2fb745d0009cd40878d44ea0633d815424",
          "diff": "571a4f597a1fd11ead8759d45260dbb2ce8c7795dedadea67d40bc59ac5dea01",
          "checked": [
            "cache",
            "safety"
          ],
          "note": "Version 2 gob round trips internal entries and reconstructs derived hash bytes."
        },
        {
          "path": "pkg/quickdup/cache_test.go",
          "status": "ok",
          "blob": "072617f3df698b5a69bcf836a4e82509367b954b",
          "diff": "d02f651093ad9aa68c351ce599dae043af633a089cda0aa7fffb31ccf5dba338",
          "checked": [
            "tests"
          ],
          "note": "Covers the word-indent round trip and all non-cacheable strategies."
        },
        {
          "path": "pkg/quickdup/filter.go",
          "status": "ok",
          "blob": "1d5078a3fbc98fbe80c730a6616fd88461b9edf2",
          "diff": "e6c0b4c6ab2b695d04129d60c2e69d456e1b1ddde7d4a2d7d6640709276ccf09",
          "checked": [
            "ignore"
          ],
          "note": "Parses documented hash forms and safely handles missing or invalid files."
        },
        {
          "path": "pkg/quickdup/filter_test.go",
          "status": "ok",
          "blob": "2bcd64f910f798819bfedad4e151f5aa86cd21b0",
          "diff": "62b571d5d0b02cf75f7dddbb1d3f6913743f434773a47f56593d220b8ca03f5e",
          "checked": [
            "tests"
          ],
          "note": "Covers raw, bracketed, prefixed, invalid, missing, and filename behavior."
        },
        {
          "path": "pkg/quickdup/strategy_score_test.go",
          "status": "ok",
          "blob": "6720c437141768f22070ee4a943b72d88f6dacd1",
          "diff": "8703f3b2774cefc32fc002f1b1bee477777e0e8b361d8df1d69250270fc9e052",
          "checked": [
            "score"
          ],
          "note": "Covers all four strategies at meaningful scoring boundaries."
        },
        {
          "path": "pkg/quickdup/types.go",
          "status": "ok",
          "blob": "81a91059940022c0a657fa6f6ab06cf1672c9a92",
          "diff": "b3152ad42d13421153d8284985e8e42192307d25bfbdec91a693e61b082e7c45",
          "checked": [
            "docs"
          ],
          "note": "Updates the ignore-file contract comment to the strategy-specific shape."
        },
        {
          "path": "scripts/quality_evidence.py",
          "status": "ok",
          "blob": "15c06d47742868f3c2ae475eb5752ece430284dc",
          "diff": "252f49b7c7a7d8dc3fdec9107a75e61cb52bfdd02db017bfad47a091640bde63",
          "checked": [
            "evidence"
          ],
          "note": "Runs uncached Go tests and atomically translates exact terminal evidence."
        },
        {
          "path": "scripts/test_quality_evidence.py",
          "status": "ok",
          "blob": "48905801a0cda53a40dd4ed88927cb36b9dd0654",
          "diff": "aa1a1bf7916e2695d009cc3acdc4351bbac7d1ab1c1c2552e312aefb9c33c551",
          "checked": [
            "contract"
          ],
          "note": "Covers config alignment, translation failures, and evidence-set conformance."
        }
      ]
    }
  7. added a commit that references this issue on Jul 16, 2026
  8. faktorial-ai commented on Jul 16, 2026

    @faktorial-ai
    Contributor

    Delivery Summary

    Why this was built

    QuickDup's maintenance contract had drifted after the library split: operators could not identify a running binary with --version, release builds did not report their tag, and the documented scoring, generated filenames, and cache scope no longer matched runtime behavior.

    Problem it solves

    Operators can now identify the exact QuickDup build before any scan begins, understand how score differs from blended rank, and reliably find strategy-specific result and ignore files. The delivery also prevents word-indent cache files from becoming unreadable because internal entry fields were not serializable.

    What changed

    The CLI now prints exactly quickdup <identity> and exits before timeout or filesystem setup, resolving identity from release injection, module/VCS metadata, or a deterministic development fallback. GoReleaser injects the release tag while retaining stripped binaries. Help and README guidance now match the 0.75 similarity default, the score-plus-complexity rank model, strategy-specific result/ignore filenames, and the fact that only word-indent is cached. Ignore parsing accepts the documented raw, bracketed, and 0x hash forms while safely handling missing or malformed files. Cache persistence now uses a version 2 wire format that round-trips internal entries and reconstructs their derived hash bytes. Focused regressions cover version behavior, all four scoring strategies, ignore handling, and cache eligibility/round-tripping; canonical evidence passed all 43 recorded tests.

    Visual explanation

    The implementation kept the existing rank flags and strategy model intact, then added two bounded paths around them. Version reporting is an early-exit control path so asking for identity cannot create scan state. Normal scans continue through the selected strategy, but persisted state is named per strategy and cache I/O is explicitly gated to word-indent. Because caches are derived local data, the serialization repair intentionally bumps the format instead of attempting to read structurally broken cache entries.

    flowchart LR
        A["quickdup --version"] --> B["Resolve release, module, VCS, or dev identity"]
        B --> C["Print one line and exit before scan or state"]
        D["Run selected duplicate strategy"] --> E["Score matches and add indentation complexity to rank"]
        E --> F["Write strategy-specific results and ignore state"]
        D --> G{"word-indent strategy?"}
        G -- Yes --> H["Use version 2 cache and restore derived hash bytes"]
        G -- No --> I["Skip cache persistence"]
        J["Focused regressions and canonical gate: 43/43 passed"] --> C
        J --> F
        J --> H
    
    Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions