Skip to content

feat(review): add gate.copycat.mode config scaffold for copycat detection - #4140

Merged
JSONbored merged 4 commits into
mainfrom
feat/copycat-detection-config-1969
Jul 8, 2026
Merged

feat(review): add gate.copycat.mode config scaffold for copycat detection#4140
JSONbored merged 4 commits into
mainfrom
feat/copycat-detection-config-1969

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • PR 1 of a multi-PR epic for Plagiarism / copycat detection #1969 (plagiarism/copycat detection, effort: XL). This PR is deliberately scoped to schema/config plumbing ONLY — no similarity/containment detection logic, no PR-fingerprint storage, no messaging. The actual detection engine (which carries real false-accusation risk and needs careful design) is explicit follow-up work, tracked separately.
  • Adds gate.copycat.mode (off | warn | label | block, default off) and gate.copycat.minScore to .gittensory.yml, following the exact wiring pattern gate.slop already uses (packages/gittensory-engine/src/focus-manifest.ts's FocusManifestGateConfig/parseGateConfig/gateConfigToJson, src/signals/focus-manifest.ts's applyGateConfigOverrides, src/types.ts's RepositorySettings, src/openapi/schemas.ts).
  • copycatMode is a DEDICATED 4-value enum, not the shared off|advisory|block GateRuleMode — the issue's tiered response is warn → label → block → strikes, where "strikes" is a separate escalation action (reusing the existing cross-repo banned-contributors ledger once wired) rather than a 5th mode value.
  • Config-as-code only, no DB column or dashboard toggle — mirrors claGateMode/lockfileIntegrityGateMode's precedent (confirmed by checking those fields are similarly absent from src/db/schema.ts, src/db/repositories.ts, src/api/routes.ts, and src/signals/settings-preview.ts).
  • This field is currently INERT. It's parsed and threaded end-to-end (manifest → effective settings → OpenAPI), but nothing evaluates it yet — no call site in src/rules/advisory.ts or src/queue/processors.ts reads copycatGateMode. An operator can set it today with zero observable effect; it exists so intent can already be declared ahead of the detection engine landing.

Scope

  • Conventional Commit title.
  • Focused — one thing (config scaffold), no detection logic bundled in.
  • Follows CONTRIBUTING.md.
  • Owner PR — linked issue eligibility gate does not apply. Advances Plagiarism / copycat detection #1969 (does not close it — this is 1 of several planned PRs).

Validation

  • git diff --check
  • npm run typecheck
  • npm run db:migrations:check / npm run db:schema-drift:check — no-ops confirmed (no DB schema touched, as expected for a config-as-code-only field).
  • npm run ui:openapi (regenerated apps/gittensory-ui/public/openapi.json) + npm run ui:openapi:check (clean) + npm run ui:openapi:settings-parity (confirms RepositorySettingsSchema matches the RepositorySettings type at 100 fields, including the 2 new ones).
  • npx vitest run test/unit/focus-manifest.test.ts — 558/558 passing, including 5 new dedicated tests (parse/round-trip the gate.copycat block, all 4 mode tiers + rejection of the wrong advisory tier, minScore clamping, byte-identical-when-absent, and resolveEffectiveSettings projection in both the set and DB-fallback branches) plus 2 existing exhaustiveness-check fixtures extended for the new fields.
  • npx vitest run test/unit/openapi.test.ts test/unit/ci-openapi-settings-parity.test.ts test/unit/docs-examples-schema.test.ts — all passing.
  • Scoped coverage on the two changed source files (packages/gittensory-engine/src/focus-manifest.ts, src/signals/focus-manifest.ts) confirms every new line is covered; the reported uncovered line ranges in each file are pre-existing gaps unrelated to this diff (verified by line number).
  • npm run test:workers, build:mcp, test:mcp-pack, ui:lint, ui:typecheck, ui:build, npm audit — not re-run locally (no worker/MCP/UI-component code touched); CI runs them authoritatively.

Safety

  • No secrets, wallet/hotkey/trust-score/reward data anywhere.
  • No auth/cookie/CORS/session changes.
  • No new decision-making logic — this PR cannot change any gate outcome (verified: no call site reads the new fields yet).
  • No UI changes — no UI Evidence section needed.
  • No docs/changelog changes needed beyond the .gittensory.yml.example / config/examples/gittensory.full.yml inline documentation for the new keys.

Notes

  • 9 files is slightly over this repo's ~5-file-ideal preference, but is the genuine minimal footprint for a correctly config-as-code-parity-wired gate field in this codebase (type definition in both src/types.ts and the mirrored packages/gittensory-engine/src/types/manifest-deps-types.ts, parse/serialize, resolver, OpenAPI schema + regenerated artifact, docs in both example files, tests) — confirmed by checking claGateMode's own footprint follows the same shape.
  • Follow-up PRs (not this one): the actual deterministic containment/similarity scorer, direction-by-timestamp logic, a new migration for PR-fingerprint storage (the issue's own scope explicitly needs a data substrate that doesn't exist today — duplicate-winner.ts's existing logic is confirmed to be pure scope-claim election, not code comparison), and the tiered gate wiring that actually reads copycatGateMode in src/rules/advisory.ts/src/queue/processors.ts.

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.73%. Comparing base (7d4117c) to head (b25d4c6).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4140   +/-   ##
=======================================
  Coverage   93.73%   93.73%           
=======================================
  Files         387      387           
  Lines       36371    36382   +11     
  Branches    13316    13323    +7     
=======================================
+ Hits        34092    34104   +12     
  Misses       1621     1621           
+ Partials      658      657    -1     
Files with missing lines Coverage Δ
packages/gittensory-engine/src/focus-manifest.ts 99.16% <100.00%> (+0.10%) ⬆️
src/openapi/schemas.ts 100.00% <ø> (ø)
src/signals/focus-manifest.ts 99.62% <100.00%> (+<0.01%) ⬆️
src/types.ts 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 8, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui b25d4c6 Commit Preview URL

Branch Preview URL
Jul 08 2026, 10:19 AM

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 8, 2026
@loopover-orb

loopover-orb Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - fixes required

Review updated: 2026-07-08 10:15:19 UTC

13 files · 2 blockers · readiness 93/100 · CI failing · blocked

🛑 Suggested Action - Manual Review

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

Why this is blocked

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.

CI checks failing

  • validate
  • validate-code
Signal Result Evidence
Code review ❌ 2 blockers No AI review summary
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 52 registered-repo PR(s), 43 merged, 486 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 52 PR(s), 486 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 52 PR(s), 486 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/docs/how-reviews-work desktop after /docs/how-reviews-work
/docs/how-reviews-work mobile after /docs/how-reviews-work (mobile)
/docs/tuning desktop after /docs/tuning
/docs/tuning mobile after /docs/tuning (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

JSONbored added 3 commits July 8, 2026 03:01
…tion

Parses and threads a new gate.copycat.mode (off/warn/label/block) and
gate.copycat.minScore end-to-end through the manifest, effective-settings
resolver, and OpenAPI schema -- config-as-code only, no DB column. The
similarity/containment detection engine that would consume this config
does not exist yet; this field is deliberately inert (parsed and threaded,
never read by any decision path) so an operator's .gittensory.yml can
already declare intent ahead of the detection engine landing in a later PR.
The scaffold PR added copycatGateMode to RepositorySettings but missed
two things docs:drift-check enforces for every *GateMode field: a
GATE_MODE_MANIFEST entry in scripts/check-docs-drift.mjs, and real
documentation on docs.how-reviews-work.tsx + docs.tuning.tsx. Both added,
honestly noting the detection engine hasn't shipped yet. Bumps the
synthetic-fixture gate-mode count in the drift-check's own test to match.
…t round-trip

gate.copycat.mode and gate.copycat.minScore are independently optional
in the source YML, but every existing gateConfigToJson round-trip test
set both together (or left both null), leaving the "only one of the
two is set" branch inside gateConfigToJson's copycat block uncovered.
npm run ui:lint runs eslint's prettier/prettier rule as an error, not
just npm run validate's plain prettier check -- the added JSX text
wrapped in a way that check rejects.
loopover-orb Bot pushed a commit that referenced this pull request Jul 15, 2026
Implements the deterministic containment/similarity engine gate.copycat.mode
was parsed for since #4140 but never acted on. Scores a PR's added lines
against a bounded, precision-first candidate set of earlier open siblings and
recently-merged PRs on the same repo, resolving copy direction by submission
timestamp so the original author is never flagged. warn surfaces an advisory
finding; label also applies a label without blocking review; block also
closes the PR and feeds the existing moderation-rules strikes ledger.

Closes #1969
JSONbored added a commit that referenced this pull request Jul 25, 2026
ui-preview.yml / ui-preview-deploy.yml (via the shared deploy-ui-preview
composite) create a "preview/pr-<N>" GitHub Environment via createDeployment
the first time a PR gets a preview build -- transient_environment: true is
only a display hint, it never triggers deletion, and nothing else in the
repo ever calls the delete-environment API. Confirmed live: 1254 of 1260
environments were preview/pr-* entries for already-closed PRs (spanning PR
#4140-#8617), none carrying protection rules -- cleaned up directly via the
API as a one-time sweep before adding this workflow.

Mirrors cache-cleanup.yml's existing fix for the identical class of
problem (GHA caches instead of environments): batched on a daily schedule,
not a pull_request:[closed] trigger, so PR-close bursts never queue a
runner per event and compete with real CI. No storage-budget urgency here
unlike the 10GB cache cap, so daily is enough.

Needs a new ENVIRONMENT_ADMIN_TOKEN secret -- deleting an environment
requires repo scope (classic PAT) or Administration:write (fine-grained
PAT); GITHUB_TOKEN can never be granted this via a permissions: block,
confirmed against GitHub's own docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

1 participant