') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Converge Copilot Instructions and Remaining Intent Files with Hub by ptr727 · Pull Request #88 · ptr727/PhotoCleaner · GitHub
Skip to content

Converge Copilot Instructions and Remaining Intent Files with Hub - #88

Closed
ptr727 wants to merge 4 commits into
chore/hub-resync-2026-08from
chore/hub-resync-intent-files-2026-08
Closed

Converge Copilot Instructions and Remaining Intent Files with Hub#88
ptr727 wants to merge 4 commits into
chore/hub-resync-2026-08from
chore/hub-resync-intent-files-2026-08

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Part of the periodic hub resync (see also #86 and the skills-tree PR from the same run). Audit
run 2026-08-29T01:09:26Z | hub b823bc4.

Stacked on #86 (targets chore/hub-resync-2026-08, not develop): the deleted
repo-config//spec/secrets.json and the rewritten AUDIT.md/OPERATIONS.md that PR
introduces are load-bearing for the CODESTYLE.md link fix and the GOVERNANCE.md Repository
Layout entry here. Retarget to develop once #86 merges.

  • Rewrite .github/copilot-instructions.md's four declared sections to the current hub
    canonical (the review runbook shrank substantially, its mechanics now delegated to
    scripts/pr_review.py). Preserve the (currently empty) Disproved Claims ledger.
  • Move the file's nine undeclared, repo-specific sections (architecture, patterns, processing
    pipeline, per-command implementation detail, test layout) into a new ARCHITECTURE.md, the
    destination spec/section-model.md declares for this content. Drop "Command Line Usage"
    outright as a duplicate of README.md's own Usage section.
  • Re-vendor CODESTYLE.md (repoint its two dead GOVERNANCE.md "Running the Linters Locally"
    links at OPERATIONS.md "Local Verification", which now holds that content since that
    section moved hub-only; adopt the hub's stronger pre-commit-gate wording; keep the repo's own
    "The Full Post-Change Set" subsection) and WORKFLOW.md (3-way merge against the hub revision
    this repo last converged with — picks up the .NET-publish artifact-naming rename and several
    D-clause wording fixes while preserving every repo-specific adaptation).
  • Adopt the hub's much-simplified .gitattributes/.editorconfig (* text=auto eol=lf blanket
    normalization, dropping the now-redundant per-path LF pins). Confirmed byte-identical via
    --renormalize, so this is a policy-text simplification only, no file content changes.
  • Update cspell.json's fleet word list (opencode, Qodo added; nugetlibrary, pypilibrary
    dropped, matching the WORKFLOW.md artifact rename).

.editorconfig-checker.json and version.json show no drift since this repo's last hub sync;
their audit intent findings are the timestamp-advisory false-positive shape (AUDIT.md
section 7).

🤖 Generated with Claude Code

CopilotAI lite review requested due to automatic review settings August 29, 2026 01:32
@coderabbitai

coderabbitaiBot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • main
  • develop

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 15b97fb2-7f0a-471a-9ab4-76fd4b5c03be

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Resync Intent Documentation and Line-Ending Policies with Hub

📝 Documentation⚙️ Configuration changes🕐 20-40 Minutes

Grey Divider

AI Description

• Move repository architecture from Copilot instructions into dedicated architecture documentation.
• Resync Copilot, coding, and workflow guidance with hub canonical policies.
• Simplify line-ending configuration and refresh fleet spelling terms.
Diagram

graph TD
H["Hub Canonical"] --> C["Copilot Bootstrap"] --> R["Review Automation"]
H --> S["Code Style"] --> O["Local Verification"]
H --> W["Workflow Contract"]
C --> A["Project Architecture"]
H --> L["Line Ending Policy"]
Loading
High-Level Assessment

The chosen approach is appropriate: keep provider-specific Copilot instructions concise, place repository architecture in its declared dedicated document, and preserve repository adaptations while re-vendoring canonical fleet text. Retaining architecture inside Copilot instructions would continue mixing provider-specific review mechanics with project-wide technical context.

Files changed (8) +313 / -700

Documentation (5) +302 / -661
copilot-instructions.mdReduce Copilot guidance to canonical bootstrap and review requirements+38/-630

Reduce Copilot guidance to canonical bootstrap and review requirements

• Replaces the expansive provider-specific runbook with concise canonical instructions that delegate mechanics to hub-hosted review automation. Routes project architecture to 'ARCHITECTURE.md' while preserving the Disproved Claims ledger contract.

.github/copilot-instructions.md

ARCHITECTURE.mdCreate dedicated project architecture and implementation reference+237/-0

Create dedicated project architecture and implementation reference

• Moves project structure, processing pipeline, command behavior, dependencies, implementation patterns, and testing guidance out of Copilot instructions. Establishes a provider-independent home for repository-specific technical context while omitting duplicated command usage examples.

ARCHITECTURE.md

CODESTYLE.mdRefresh canonical verification and pre-commit guidance+4/-4

Refresh canonical verification and pre-commit guidance

• Repoints local linter guidance from the removed governance section to 'OPERATIONS.md' and strengthens the recommendation for a working local commit gate. Updates shell verification language while preserving the repository-specific post-change checklist.

CODESTYLE.md

GOVERNANCE.mdRegister the dedicated architecture document in repository layout+1/-1

Register the dedicated architecture document in repository layout

• Updates the repository layout to describe Copilot instructions as bootstrap and review guidance. Adds 'ARCHITECTURE.md' as the canonical location for project architecture, pipeline, command details, and test layout.

GOVERNANCE.md

WORKFLOW.mdResync workflow contracts and artifact naming with hub+22/-26

Resync workflow contracts and artifact naming with hub

• Adopts current hub terminology for .NET publish, NuGet, and PyPI artifacts and refines release, coverage, cleanup, Docker, source-only, deployment, and merge-bot contracts. Preserves this repository's workflow-specific adaptations while correcting D-clause wording and examples.

WORKFLOW.md

Other (3) +11 / -39
.editorconfigAlign editor line-ending guidance with simplified Git normalization+3/-7

Align editor line-ending guidance with simplified Git normalization

• Replaces detailed per-path commentary with the canonical relationship between EditorConfig, Git normalization, and CI verification. Clarifies that non-.NET repositories retain the inert C# section under the whole-file model.

.editorconfig

.gitattributesNormalize all detected text files with concise LF defaults+6/-30

Normalize all detected text files with concise LF defaults

• Replaces opt-out normalization and execution-sensitive path pins with 'text=auto eol=lf'. Retains explicit CRLF exceptions for Windows batch and command scripts.

.gitattributes

cspell.jsonRefresh fleet vocabulary for current tooling and artifact names+2/-2

Refresh fleet vocabulary for current tooling and artifact names

• Adds 'opencode' and 'Qodo' to the accepted vocabulary. Removes obsolete 'nugetlibrary' and 'pypilibrary' terms after workflow artifact renaming.

cspell.json

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new ARCHITECTURE.md introduces a product-name typo and inconsistent hard-coded test counts that should be corrected for documentation accuracy.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR continues the hub resync by converging Copilot/bootstrap guidance and repo documentation with the current hub canon, while extracting repo-specific architecture/process details into a dedicated ARCHITECTURE.md and updating supporting intent files (workflow contract docs, spelling dictionary, and EOL normalization rules).

Changes:

  • Rewrite .github/copilot-instructions.md to the current hub “bootstrap + review runbook” shape and move repo architecture/process documentation into a new ARCHITECTURE.md.
  • Re-vendor/merge governance docs (WORKFLOW.md, CODESTYLE.md, GOVERNANCE.md) to match updated hub wording and link targets (notably routing local verification references to OPERATIONS.md).
  • Simplify line-ending policy enforcement via .gitattributes / .editorconfig and refresh the fleet cspell word list.
File summaries
FileDescription
WORKFLOW.mdUpdates the CI/CD contract text and examples to the current hub canonical.
GOVERNANCE.mdAdjusts repository layout docs to point architecture content to ARCHITECTURE.md.
cspell.jsonUpdates the allowed word list to match current fleet vocabulary.
CODESTYLE.mdRepoints “local verification” references to OPERATIONS.md and refreshes wording around pre-commit gates and shell checks.
ARCHITECTURE.mdNew document capturing repo-specific architecture, pipeline, and test layout content formerly in Copilot instructions.
.github/copilot-instructions.mdConverges Copilot bootstrap + review runbook sections with hub, preserving the Disproved Claims ledger structure.
.gitattributesSimplifies git-level EOL normalization to text=auto with LF default and CRLF for Windows scripts.
.editorconfigSimplifies line-ending commentary and keeps LF default with a bat/cmd CRLF exception.
Review details

Suppressed comments (1)

ARCHITECTURE.md:168

  • This section also hard-codes a different test count for CommandLineTests.cs than the earlier project-structure list. To keep the doc consistent (and reduce future maintenance), consider removing the per-file count here as well.
 - `DateInferenceTests.cs`: Core date inference functionality (33 tests)
- `DateInferenceEdgeCasesTests.cs`: Date inference edge cases and integration (19 tests)
- `CommandLineTests.cs`: Command line parsing and validation (24 tests)
- `ProcessTaskTests.cs`: Process task tests (61 tests)
  • Files reviewed: 8/8 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
@qodo-code-review

qodo-code-reviewBot commented Aug 29, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0)📘 Rule violations (2)📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Nonexistent test suite documented✓ Resolved🐞 Bug⚙ Maintainability
Description
The test inventory and test-architecture section both claim a DateInferenceEdgeCasesTests.cs suite
exists, but that file is absent and the date tests live in DateInferenceTests.cs. This makes the
newly designated architecture authority point contributors and agents to a nonexistent test
location.
Code

ARCHITECTURE.md[R42-44]

+ - `DateInferenceTests.cs`: Core date inference functionality tests (33 tests)+ - `DateInferenceEdgeCasesTests.cs`: Edge cases and comprehensive scenarios (19 tests)+ - `CommandLineTests.cs`: Command line parsing and validation tests (15 tests)
Evidence
The documented edge-case filename does not exist; the actual date-inference test class and tests are
contained in DateInferenceTests.cs.

ARCHITECTURE.md[41-45]
ARCHITECTURE.md[164-168]
PhotoCleanerTests/DateInferenceTests.cs[1-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Remove the nonexistent date-edge-case test file entry and align the test inventory with the actual suite.
## Issue Context
`PhotoCleanerTests` contains `DateInferenceTests.cs` but no `DateInferenceEdgeCasesTests.cs`; the duplicate stale reference later in the document should be corrected too.
## Fix Focus Areas
- ARCHITECTURE.md[42-44]
- ARCHITECTURE.md[164-168]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Nonexistent production files documented✓ Resolved🐞 Bug⚙ Maintainability
Description
The project structure claims HttpClientFactory.cs and AssemblyInfo.cs exist and provide
Polly/User-Agent behavior, but neither file nor the described implementation exists in the
application tree. Agents following this architecture guide will search for or preserve components
that are not part of the project.
Code

ARCHITECTURE.md[R38-39]

+ - `HttpClientFactory.cs`: Polly resilience pipeline (retry, circuit breaker) and `SocketsHttpHandler` connection pooling+ - `AssemblyInfo.cs`: Assembly metadata (app name, version) used by `HttpClientFactory` for User-Agent header
Evidence
The new inventory names two concrete source files, but the actual application transitions directly
from Extensions.cs/FileEnumerator.cs to other existing components and its logger implementation
is in LoggerFactory.cs; no HttpClientFactory class exists.

ARCHITECTURE.md[35-40]
PhotoCleaner/LoggerFactory.cs[4-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Remove or replace architecture entries for production files that do not exist.
## Issue Context
The application tree contains `LoggerFactory.cs`, but no `HttpClientFactory.cs` or `AssemblyInfo.cs`, and no C# implementation references Polly or User-Agent handling.
## Fix Focus Areas
- ARCHITECTURE.md[38-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Video conversion tiers misstated✓ Resolved🐞 Bug⚙ Maintainability
Description
The guide says .mts and .m2ts are remuxed and omits .m2t and .asf, but the implementation
remuxes only .m2t/.mkv and re-encodes .asf with the other listed formats. This gives
contributors the wrong behavioral contract for three supported video extensions.
Code

ARCHITECTURE.md[R173-175]

+### Video Conversion Logic++- **Three-tier approach**: Remux (.mts, .m2ts, .mkv) -> Re-encode (.wmv, .avi, .3gp, .gif) -> Audio-only (.mov/.mp4 with PCM)
Evidence
ProcessTask defines the exact frozen sets used for conversion, and they conflict directly with the
added tier list.

ARCHITECTURE.md[173-175]
PhotoCleaner/ProcessTask.cs[34-51]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Correct the documented video conversion tiers to match `ProcessTask`.
## Issue Context
The remux set is `.m2t` and `.mkv`; the re-encode set is `.asf`, `.wmv`, `.avi`, `.3gp`, and `.gif`. `.mts` and `.m2ts` are supported but are not members of either conversion set.
## Fix Focus Areas
- ARCHITECTURE.md[173-175]
- PhotoCleaner/ProcessTask.cs[34-51]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
4. PR title capitalization incorrect 📘 Rule violation⚙ Maintainability
Description
The major words tree, docs, remaining, intent, files, and hub are lowercase rather than
title case. Capitalize those words while preserving lowercase short bind words.
Code

.github/copilot-instructions.md[R18-19]

+Use an imperative subject of at most 72 characters with no trailing period. Use US English and+title case with lowercase short bind words. Do not add `Co-Authored-By:` unless requested. Do not
Evidence
PR Compliance ID 2826923 requires English title case with only short bind words lowercase; the
supplied title leaves multiple major words lowercase. The changed instructions explicitly restate
the title-case requirement.

Rule 2826923: Use title case with lowercase short bind words in pull request titles
.github/copilot-instructions.md[18-19]


5. CODESTYLE link escapes repository✓ Resolved🐞 Bug⚙ Maintainability
Description
Because ARCHITECTURE.md now lives at the repository root, ../CODESTYLE.md resolves outside the
repository instead of to the existing root-level guide. The new architecture page therefore contains
a broken development-workflow link.
Code

ARCHITECTURE.md[148]

+See [`CODESTYLE.md`](../CODESTYLE.md) for build requirements, formatting commands, and tooling.
Evidence
The added document is at ARCHITECTURE.md, while the referenced target is the sibling root file
CODESTYLE.md; the current ../ path cannot resolve to it.

ARCHITECTURE.md[146-148]
CODESTYLE.md[1-3]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Fix the broken CODESTYLE link in the new root-level architecture document.
## Issue Context
`ARCHITECTURE.md` and `CODESTYLE.md` are siblings at the repository root, so `../CODESTYLE.md` escapes the repository.
## Fix Focus Areas
- ARCHITECTURE.md[148-148]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Wrong JSON context named✓ Resolved🐞 Bug⚙ Maintainability
Description
The JSON source-generation section names a nonexistent SourceGenerationContext; ExifToolJson is
actually serialized through ExifToolJsonContext. Following the document would produce invalid code
or fail to locate the generated serializer contract.
Code

ARCHITECTURE.md[R217-220]

+## JSON Source Generation++Uses `SourceGenerationContext` for AOT-compatible JSON serialization of `ExifToolJson` metadata.+Uses `ImmichJsonContext` for AOT-compatible JSON serialization of Immich API models.
Evidence
The source declares and consumes ExifToolJsonContext, while no SourceGenerationContext is
defined.

ARCHITECTURE.md[217-220]
PhotoCleaner/ExifToolJson.cs[326-327]
PhotoCleaner/MediaUtilities.cs[100-103]
PhotoCleaner/ImmichApiModels.cs[47-49]
PhotoCleaner/VerifyResult.cs[21-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Replace the nonexistent JSON context name with the implementation's actual generated context.
## Issue Context
`ExifToolJsonContext` handles `ExifToolJson`; `ImmichJsonContext` and `ImmichVerifyJsonContext` are separate contexts for their respective models.
## Fix Focus Areas
- ARCHITECTURE.md[217-220]
- PhotoCleaner/ExifToolJson.cs[326-327]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Supported extensions list incomplete✓ Resolved🐞 Bug⚙ Maintainability
Description
The architecture guide's exhaustive “Supported” list omits .asf, .m2t, and .psd, although
MediaUtilities.SupportedExtensions accepts all three. Readers relying on the new canonical
architecture document will incorrectly conclude those file types are skipped.
Code

ARCHITECTURE.md[R213-215]

+## File Processing Extensions++Supported: `.3gp`, `.arw`, `.avi`, `.cr2`, `.dng`, `.gif`, `.heic`, `.heif`, `.jpeg`, `.jpg`, `.m2ts`, `.mkv`, `.mov`, `.mp4`, `.mts`, `.nef`, `.orf`, `.png`, `.rw2`, `.tif`, `.tiff`, `.wmv`
Evidence
The implementation's authoritative frozen set contains .asf, .m2t, and .psd, while all three
are absent from the added list.

ARCHITECTURE.md[213-215]
PhotoCleaner/MediaUtilities.cs[9-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Synchronize the documented supported-extension list with `MediaUtilities.SupportedExtensions`.
## Issue Context
The implementation additionally includes `.asf`, `.m2t`, and `.psd`.
## Fix Focus Areas
- ARCHITECTURE.md[213-215]
- PhotoCleaner/MediaUtilities.cs[9-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. PR title exceeds limit 📘 Rule violation⚙ Maintainability
Description
The PR title is 80 characters, exceeding the 72-character maximum. Shorten it while retaining an
imperative subject and no trailing period.
Code

.github/copilot-instructions.md[18]

+Use an imperative subject of at most 72 characters with no trailing period. Use US English and
Evidence
PR Compliance ID 2826914 limits pull request titles to 72 characters; the supplied title `Converge
copilot-instructions.md, tree docs, and remaining intent files with hub` is 80 characters. The
changed instructions also restate the same 72-character contract.

Rule 2826914: Pull request titles use imperative mood, ≤72 chars, no trailing period
.github/copilot-instructions.md[18-18]



Informational

9. Obsolete trimming pattern prescribed✓ Resolved🐞 Bug⚙ Maintainability
Description
The architecture guide prescribes a Trim call containing a duplicate space and a string-based
pattern that the current implementation no longer uses. Since this section states a coding
convention, it directs future changes away from the repository's actual span-based implementation.
Code

ARCHITECTURE.md[R94-96]

+- Always use array syntax for arguments: `["-arg1", "value"]`+- Use `BufferedCommandResult` for output capture, `CommandResult` for fire-and-forget+- JSON trimming pattern: `result.StandardOutput.Trim(' ', '\n', '\r', ' ', '[', ']')`
Evidence
The added convention differs from the actual expression used by the only ExifTool JSON parsing path.

ARCHITECTURE.md[94-96]
PhotoCleaner/MediaUtilities.cs[86-103]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Update or remove the stale JSON trimming convention.
## Issue Context
The implementation trims a `ReadOnlySpan<char>` with `Trim([' ', '\n', '\r', '[', ']'])`; the documented expression duplicates the space character and no longer matches the code.
## Fix Focus Areas
- ARCHITECTURE.md[94-96]
- PhotoCleaner/MediaUtilities.cs[91-91]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 13 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread.github/copilot-instructions.md
Comment thread.github/copilot-instructions.md
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
Comment threadARCHITECTURE.md Outdated
@ptr727ptr727 changed the title Converge copilot-instructions.md, tree docs, and remaining intent files with hubConverge Copilot Instructions, Tree Docs, and Remaining Intent Files with HubAug 29, 2026
@ptr727ptr727 changed the title Converge Copilot Instructions, Tree Docs, and Remaining Intent Files with HubConverge Copilot Instructions and Remaining Intent Files with HubAug 29, 2026
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Re: suppressed finding on ARCHITECTURE.md:168 (duplicate/drifted test-count in the Test Architecture section's now-removed 'Test Categories' sub-list) - fixed in 5a625fc, same commit that fixed the parallel finding above it. That whole redundant sub-list (a partial, already-drifted duplicate of the fuller Project Structure list) was removed rather than re-synced, since keeping two lists of the same fact in sync is exactly what keeps re-drifting.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

WORKFLOW.md contains a repo-specific statement about publish-release.yml lacking a plan job/single-job gating that does not match the current workflow structure.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

WORKFLOW.md:171

  • D4.1’s repo-specific note is out of date with the current publish-release.yml: this repo does run a plan job (and a separate validate job) and gates the publish reusable workflow on both needs.plan.outputs.publish and needs.validate.result. As written, the doc says there is no plan job and a single-job gate on github.ref_name, which no longer matches the workflow and can mislead future edits to the release chain.
- **D4.1 Gated single-branch publish.** Output: PRs smoke-test and publish nothing. A **human merge never auto-publishes**. The fleet shape puts a first `plan` job (`publish-plan-task.yml`) in front and gates every job on it, covering a **code-affecting bot push to `main`**, a **dispatch** of `main`/`develop`, and a **main-only weekly schedule**. **This repo carries no plan job and no push trigger at all**: `publish-release.yml` runs on `workflow_dispatch` or the weekly `main`-only schedule, and its single job gates on `github.ref_name` being `main` or `develop`, so a dispatch from a feature branch is a no-op. Nothing publishes on a push, bot or human, and accumulated changes ship in the next scheduled or dispatched run. Each run builds one branch.
  • Files reviewed: 8/8 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

ptr727 added a commit that referenced this pull request Aug 29, 2026
CI's repo_gate.py --check eol/eol-coverage (reached via the pin bumped
in a72c48c) now requires a '* text=auto eol=<ending>' default plus
explicit *.bat/*.cmd CRLF pins, the hub's new .gitattributes shape.
The old '* -text' plus per-path LF pins model this PR left untouched
fails both checks. Confirmed byte-identical via --renormalize (no file
content changes, policy-text only), and confirmed clean locally against
the same repo_gate.py checks CI runs.
This duplicates one commit from the intent-files PR (#88, stacked on
this branch), which will become empty and drop out once that branch is
rebased onto this commit.
@ptr727
ptr727force-pushed the chore/hub-resync-intent-files-2026-08 branch from 5a625fc to 53c35f5CompareAugust 29, 2026 03:04
ptr727 added a commit that referenced this pull request Aug 29, 2026
The prior commit adopted the hub's simplified .gitattributes but left
.editorconfig's comment block describing the superseded per-type-pin
model (shell/Dockerfiles/uv.lock/.py-by-path/husky hook pins), which a
review caught as now internally inconsistent within this PR. Sync it to
the same hub canonical wording used for .gitattributes.
This duplicates the matching hunk in the stacked intent-files PR (#88),
which will become empty and drop out once that branch is rebased onto
this commit.
…es with hub
Rewrite .github/copilot-instructions.md's four declared sections to the
current hub canonical (the review runbook shrank substantially, its
mechanics now delegated to scripts/pr_review.py). Move this file's nine
undeclared, repo-specific sections (architecture, patterns, processing
pipeline, per-command implementation detail, test layout) into a new
ARCHITECTURE.md, the destination spec/section-model.md declares for
this content; drop the 'Command Line Usage' section outright as a
duplicate of README.md's own Usage section. Preserve the (currently
empty) Disproved Claims ledger and each of CODESTYLE.md/WORKFLOW.md's
own repo-specific adaptations verbatim across the re-vendor.
Re-vendor the remaining intent files against the current hub canonical:
CODESTYLE.md (repoint its two dead GOVERNANCE.md 'Running the Linters
Locally' links at OPERATIONS.md 'Local Verification', which now holds
that content; adopt the hub's stronger pre-commit-gate wording; keep
the repo's own 'The Full Post-Change Set' subsection), WORKFLOW.md
(3-way merge against the hub revision this repo last converged with,
picking up the .NET-publish artifact-naming rename and several D-clause
wording fixes while preserving every repo-specific adaptation),
.gitattributes and .editorconfig (adopt the hub's much-simplified
'* text=auto eol=lf' blanket normalization, dropping the now-redundant
per-path LF pins; confirmed byte-identical via --renormalize, so this
is a policy-text simplification only), and cspell.json's fleet word
list (opencode, Qodo added; nugetlibrary, pypilibrary dropped, matching
the WORKFLOW.md artifact rename).
.editorconfig-checker.json and version.json show no drift since this
repo's last hub sync; their audit 'intent' findings are the timestamp
advisory's known false-positive shape (AUDIT.md section 7).
Depends on #86 (this branch is stacked on chore/hub-resync-2026-08),
since the deleted repo-config/spec/secrets.json and the rewritten
AUDIT.md/OPERATIONS.md that PR introduces are load-bearing for the
CODESTYLE.md link fix and the GOVERNANCE.md Repository Layout entry
here.
Audit run 2026-08-29T01:09:26Z | hub b823bc4
This content was moved verbatim out of copilot-instructions.md in the
prior commit, and review against the actual current source surfaced
several pre-existing staleness bugs in it, not introduced by the move
but newly caught because moving it to a canonical architecture doc drew
a full review pass:
- PhotoPrims -> PhotoPrism (spelling).
- ../CODESTYLE.md -> ./CODESTYLE.md (ARCHITECTURE.md lives at the repo
root now, not under .github/; the old relative path escaped the repo).
- Removed HttpClientFactory.cs and AssemblyInfo.cs entries: neither file
exists, and nothing in the tree uses Polly or sets a User-Agent header.
Added the real, previously-undocumented LoggerFactory.cs.
- Removed the DateInferenceEdgeCasesTests.cs entry (does not exist) and
every hard-coded per-file test count, confirmed already drifted in two
places (CommandLineTests.cs: 15 vs 24; the whole PhotoCleanerTests
Project: 300 vs the actual 260) and structurally guaranteed to drift
again the next time a test is added.
- Supported-extensions list: added .asf, .m2t, .psd, confirmed present
in MediaUtilities.SupportedExtensions but missing from the list.
- Video conversion tiers: corrected against ProcessTask's actual
s_remuxExtensions/s_reencodeExtensions/s_reencodeAudioExtensions sets
(remux is .m2t/.mkv, not .mts/.m2ts/.mkv; re-encode includes .asf).
- JSON source generation: SourceGenerationContext does not exist;
ExifToolJson uses ExifToolJsonContext, and the Immich verify protocol's
ImmichVerifyJsonContext was undocumented entirely.
- Trim pattern: the real code trims a ReadOnlySpan<char> with a 5-char
array (no duplicate space), not a 6-arg string Trim.
@ptr727
ptr727force-pushed the chore/hub-resync-intent-files-2026-08 branch from 53c35f5 to c684190CompareAugust 29, 2026 03:11
@ptr727
ptr727 requested a lite review from CopilotAugust 29, 2026 03:12

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

WORKFLOW.md repo-specific notes are inconsistent with the current .github/workflows/* behavior (paths-filter/trigger/plan-job shape), and CODESTYLE.md references a non-existent local catalog/snippets/ path without clarifying it is hub-hosted.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment threadWORKFLOW.md Outdated
Comment threadWORKFLOW.md Outdated
Comment threadCODESTYLE.md Outdated
Review caught that this repo's actual test-pull-request.yml and
publish-release.yml no longer match the repo-specific deviations
WORKFLOW.md's D1.1/D1.4/D1.5/D4.1 claimed, predating this resync (the
git log's 'Adopt .NET Publish Workflow Schema' migration). Verified
against the current workflow YAML directly:
- test-pull-request.yml DOES carry a changes job with a dorny/paths-filter
(one combined 'release' filter excluding .github/workflows/**), contra
the 'this repo runs no paths filter' claim in both D1.1 and D1.4.
- check-workflow-status needs [changes, validate, smoke-build] and treats
each as success-or-skipped, contra D1.5's 'demands success from both...
since neither is ever skipped' claim.
- publish-release.yml DOES carry a plan job gating validate/publish on
its outputs.publish, contra D4.1's 'this repo carries no plan job...
single job' claim. It does still have no push trigger at all, which is
the part of the old claim that was correct.
Rewrote D1.1/D1.4/D1.5/D4.1 and the S1/S2/S3/S5/S6 scenario table rows
to match the actual current workflows.
Also reworded a CODESTYLE.md sentence naming catalog/snippets/ as a
plain path to make explicit it's hub-only and not carried here (intent
fidelity, judged by meaning, not byte-locked - direct fix rather than a
decline).

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces/solidifies a routing mismatch where AGENTS.md still points architecture content at .github/copilot-instructions.md instead of ARCHITECTURE.md.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

.github/copilot-instructions.md:14

  • This file now says architecture/pipeline details live in ARCHITECTURE.md, but AGENTS.md still routes those details to .github/copilot-instructions.md. That mismatch will send agents/readers to the wrong document; update AGENTS.md (and any other routers) to point architecture content at ARCHITECTURE.md to keep the instruction map consistent.
Do not duplicate rules from `AGENTS.md`, `GOVERNANCE.md`, `CODESTYLE.md`, or `WORKFLOW.md` here.
This file contains only Copilot-specific bootstrap and output requirements. This project's
architecture, processing pipeline, and per-command implementation details live in
[`ARCHITECTURE.md`](../ARCHITECTURE.md).

ARCHITECTURE.md:90

  • The exiftool CliWrap example uses _fileInfo.FullName, but the codebase pattern uses a filePath (or similar) variable; as written, the snippet won't compile and may mislead contributors copying it. Adjust the example to match the actual call style used in MediaUtilities.
BufferedCommandResult result = await Cli.Wrap("exiftool")
.WithArguments(["-groupNames", "-json", "-validate", "-all", _fileInfo.FullName])
.ExecuteBufferedAsync();

- **Files reviewed:** 6/6 changed files
- **Comments generated:** 0 new
- **Review effort level:** Lite
</details>

AGENTS.md's own preamble (not the verbatim section below it) still
routed architecture/pipeline/test-layout content at
.github/copilot-instructions.md, stale since this PR moved that content
to ARCHITECTURE.md. Repointed both routing sentences.
ARCHITECTURE.md's External Tool Execution Pattern example used
_fileInfo.FullName, which does not compile against the actual call in
MediaUtilities.cs (uses filePath). Fixed the example to match.
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Re: two suppressed findings from the last round (both fixed in 30c5819):

  1. AGENTS.md:14/copilot-instructions.md mismatch - AGENTS.md's own preamble (local, not the verbatim section below it) still routed architecture/pipeline/test-layout content at .github/copilot-instructions.md; repointed both mentions at ARCHITECTURE.md.
  2. ARCHITECTURE.md:90 exiftool example - used _fileInfo.FullName, which doesn't match the actual MediaUtilities.cs call (filePath); fixed the example.

@ptr727
ptr727 requested a lite review from CopilotAugust 29, 2026 03:27

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The documentation and instruction-set convergence matches the referenced workflow/YAML behavior and introduces no inconsistencies in the updated cross-references.

Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

ptr727 added a commit that referenced this pull request Aug 29, 2026
…ets (#86)
* Converge instruction set with hub, retire hub-hosted repo-config/secrets
Re-vendor AGENTS.md and GOVERNANCE.md's declared-verbatim sections from
the current hub canonical (hub main@b823bc4). Delete repo-config/*.json,
repo-config/README.md, and spec/secrets.json: per spec/divergences.json
these are 'retire' dispositions, hub-hosted and checked from a hub
checkout (repo-config/configure.sh, spec/audit.py) rather than carried
here. Rewrite AUDIT.md's General Settings/Rulesets/Secrets sections to
point at those hub tools instead of the now-deleted local payloads, add
the now-required OPERATIONS.md 'Local Verification' leading section,
and sweep every other inbound reference to the deleted paths across
GOVERNANCE.md, WORKFLOW.md, and host-tools.json.
Also fix publish-release.yml's 'publish' job: its explicit if: bypassed
the implicit needs-succeeded gate, so a failed validate job would not
have blocked a publish. Add needs.validate.result == 'success'.
Audit run 2026-08-29T01:09:26Z | hub b823bc4
* Bump the hub-hosted workflow pin past the retire dead-path exemption
CI's prose gate (validate-task.yml) flagged 6 dead-path findings against
spec/secrets.json and repo-config/README.md, both deleted by the prior
commit. Per RESYNC.md section 4: a repo's pinned validate-task.yml SHA
can predate the retire disposition's own dead-path exemption in
prose_lint.py's HUB_HOSTED set. Confirmed: the previous pin
(74ef727a7aa96493bcd5bc2ce49b2977721678a3) predates both exemption
commits (7787662 for spec/secrets.json, e31d3fc for repo-config/), per
git merge-base --is-ancestor. Bump every ptr727/ProjectTemplate
reusable-workflow uses: in this repo's own workflows to the current hub
main (b823bc493fcdc47e9d9d9d2fc183e3ca10114146), which contains both.
Verified locally: running the current hub prose_lint.py against this
branch's diff now finds 0 violations.
* Fix .NET Format task's unordered CSharpier/build race
.vscode/tasks.json's .NET Format task declared dependsOn
[CSharpier Format, .NET Build] with no dependsOrder, so VS Code's
default (parallel) let the build read source while CSharpier was still
rewriting it, producing a nondeterministic local run. Add
dependsOrder: sequence so CSharpier finishes before the build starts,
matching OPERATIONS.md 'Local Verification''s documented ordering.
* Silence SC1091 on the Husky-generated pre-commit hook's sourced line
The pin bump in a72c48c reaches the hub's newer validate-task.yml, whose
shellcheck/shfmt discovery now correctly picks up .husky/pre-commit as
a shebang-executed extensionless script (per the shell-codestyle
skill's discovery rule) and lints it for the first time. It found
SC1091 on the '. $(dirname "$0")/_/husky.sh' line, which shellcheck
can't follow since that file is generated at husky-install time and
absent at lint time.
Not a hub defect: the hub's own canonical
catalog/snippets/husky/pre-commit template already carries this exact
directive comment. PhotoCleaner's actual generated hook was just
missing it. Verified dotnet husky install does not overwrite an
existing .husky/pre-commit, so the fix is stable across reinstalls.
Confirmed clean locally: shellcheck and shfmt both exit 0 on the file
now.
* Adopt the hub's simplified .gitattributes, required by the bumped pin
CI's repo_gate.py --check eol/eol-coverage (reached via the pin bumped
in a72c48c) now requires a '* text=auto eol=<ending>' default plus
explicit *.bat/*.cmd CRLF pins, the hub's new .gitattributes shape.
The old '* -text' plus per-path LF pins model this PR left untouched
fails both checks. Confirmed byte-identical via --renormalize (no file
content changes, policy-text only), and confirmed clean locally against
the same repo_gate.py checks CI runs.
This duplicates one commit from the intent-files PR (#88, stacked on
this branch), which will become empty and drop out once that branch is
rebased onto this commit.
* Sync .editorconfig's line-ending comment with the new .gitattributes
The prior commit adopted the hub's simplified .gitattributes but left
.editorconfig's comment block describing the superseded per-type-pin
model (shell/Dockerfiles/uv.lock/.py-by-path/husky hook pins), which a
review caught as now internally inconsistent within this PR. Sync it to
the same hub canonical wording used for .gitattributes.
This duplicates the matching hunk in the stacked intent-files PR (#88),
which will become empty and drop out once that branch is rebased onto
this commit.
@ptr727
ptr727 deleted the branch chore/hub-resync-2026-08August 29, 2026 03:46
@ptr727ptr727 closed this Aug 29, 2026
Sign up for freeto 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.

2 participants

@ptr727