diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..b9af2e9d --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,51 @@ +# GitHub Copilot Instructions — Innamark + +Primary audience: GitHub Copilot. Other agents should follow `AGENTS.md` and the closest +subproject `AGENTS.md`; reading this file is optional and only adds Copilot-tuned completion hints. + +**Read `AGENTS.md` first** for the shared rules (monorepo layout, tooling baseline, invariants, +working rules, style baseline, AI-assistance marker, secrets/network policy, PR sizing). Then read +the closest subproject `AGENTS.md`. This file only adds Copilot-specific behavior on top. + +## 0. Scope and role +- Act as a senior engineer supporting repository users (developers, architects, and maintainers). +- Be direct and implementation-focused. +- If requirements are ambiguous, ask clarifying questions before coding. +- If uncertain, say "I'm not sure" instead of guessing. +- Prefer a focused change with a clarifying question over a large speculative refactor + +## 1. Operational boundaries +- Never commit, push, merge, deploy, publish, or modify repository settings unless explicitly asked. +- Do not install dependencies, delete files, or change public APIs without proposing first. +- Keep changes scoped; avoid unrelated refactors. +- Do not read or print secrets, tokens, or local `.env` files. + +## 2. Where to look first (Copilot completion hints) +Concrete file paths that improve completion quality: +- `watermarker/src/commonMain/kotlin/watermarkers/text/PlainTextWatermarker.kt` +- `watermarker/src/commonMain/kotlin/types/watermarks/` +- `watermarker/src/commonMain/kotlin/types/responses/` (`Status`, `Result`) +- `cli/src/main/kotlin/Main.kt` +- `webinterface/src/jsMain/kotlin/` +- `docs/docs/03-usage/` and `docs/docs/04-development/` + +## 3. Copilot-specific reminders +- When generating or significantly modifying a Kotlin file, add the AI-assistance marker exactly + as defined in the root `AGENTS.md` (top-level `//` line after the license header, before + `package`). Do not place it inside KDoc. +- Mirror the matching workflow in `.github/workflows/` for touched paths when validating changes + locally (`test_watermarker.yml`, `test_cli.yml`, `test_webinterface.yml`, `test_docusaurus.yml`). +- For algorithm constraints, deprecated APIs (`ZipFileWatermarker`), preferred builders + (`InnamarkTagBuilder`), and per-subproject test/build commands: defer to `AGENTS.md` and the + subproject `AGENTS.md` rather than restating them here. + +## 4. Documentation and PR rules (Copilot) +- Update docs when user-facing behavior changes (numbered kebab-case files; add sequentially). +- PR titles: conventional commits with component scope (full format in `CONTRIBUTING.md`). + +## 5. Maintainer note — keeping this file effective +Internal guidance for whoever edits this file (not runtime rules for Copilot): +- Keep it short, structured, and imperative. +- Prefer concrete project facts and runnable commands over generic advice. +- Avoid duplicating content from `AGENTS.md`; link or defer instead. +- Add examples only when they clarify a non-obvious rule. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..12230837 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,102 @@ +# AGENTS.md + +Repository-wide guidance for all coding agents in this monorepo. + +## Read order and precedence +- Start here for global rules. +- Then read the closest subproject file (nearest file wins): + - `watermarker/AGENTS.md` + - `cli/AGENTS.md` + - `webinterface/AGENTS.md` + - `docs/AGENTS.md` +- For GitHub Copilot-specific behavior, also read `.github/copilot-instructions.md`. + +## Monorepo layout +- This repository has **independent builds** per subproject; there is no root Gradle build. +- Subprojects: + - `watermarker/`: Kotlin Multiplatform core library (JVM + JS) + - `cli/`: Kotlin/JVM CLI app consuming `watermarker-jvm` + - `webinterface/`: Kotlin/JS KVision UI consuming `watermarker` + - `docs/`: Docusaurus 3 documentation site +- `cli/` and `webinterface/` consume the **locally published** `watermarker` artifact. When touching + library code, publish first from `watermarker/`: + + ```bash + cd watermarker && ./gradlew publishToMavenLocal + ``` + +## Tooling baseline +- Kotlin subprojects (`watermarker/`, `cli/`, `webinterface/`): JDK 21, Gradle wrapper from the + subproject folder. +- `docs/`: Node 18 with yarn. +- Always run commands from the relevant subproject directory. + +## Global invariants +- Innamark uses whitespace replacement (base-4 alphabet: `\u2008`, `\u2009`, `\u202F`, `\u205F`). +- Separator is `\u2004` (`DefaultTranscoding.SEPARATOR_CHAR`). +- Capacity is based on **regular-space count**, not total text length. +- Watermark repetition across the cover is intentional for robustness; do not remove it. +- Prefer `InnamarkTagBuilder` for new watermark creation paths. +- `ZipFileWatermarker` is deprecated; do not extend it. + +## Working rules +- Run commands from the relevant subproject directory. +- Keep diffs focused; avoid drive-by reformatting. +- Keep Fraunhofer license headers intact in source files (see `CONTRIBUTING.md` → License Header + for the exact block). +- Add tests for behavioral changes and keep docs in `docs/` in sync for user-facing changes. +- Do not commit, push, merge, release, or deploy unless explicitly requested by the user. +- Do not install dependencies, fetch from the network, delete files, or change public APIs without + proposing the change first. +- Do not read or print secrets, tokens, or local `.env` files; if such content is encountered, + stop and ask before continuing. +- Soft recommendation: keep individual change sets under ~1000 LOC (see `CONTRIBUTING.md` for the + full PR sizing guidance). + +## Testing policy +- `watermarker/` is the only subproject with a mature automated test suite and should remain fully + tested. +- For `watermarker/`, behavioral changes should come with tests unless there is a strong reason not to. +- `cli/` and `webinterface/` testing is optional today, not mandatory; add tests when practical, + but do not block small focused changes solely on missing new tests there. +- File-based behaviors should reuse existing fixtures from the `samples/` folder where possible + instead of inventing new ad-hoc samples. + +## Style and quality baseline +- Kotlin style: 4 spaces, hard wrap at 100 chars, KDoc for public APIs. +- Follow Kotlin KDoc syntax: `https://kotlinlang.org/docs/kotlin-doc.html`. +- Every class/interface/object should have valid KDoc. +- Methods/functions with substantial logic should have valid KDoc when it improves generated docs + and maintainability. +- Inline comments should stay light; prefer short one-sentence comments only for long or difficult + code blocks. +- Tests do not need extra explanatory comments unless a case is genuinely non-obvious. +- Watermarker library: value-based error handling (`Status`/`Result`), avoid exceptions in core. +- Every Kotlin file should keep the Fraunhofer license header and a copyright year range from the + original creation year to the latest modification year. On any change to a file, bump the end of + the range to the current year. +- If an AI assistant makes a non-trivial logic change to a Kotlin file (i.e. anything beyond pure + formatting, renames, or comment-only edits), add the AI-assistance marker: + + ```kotlin + // This file was developed with AI assistance. + ``` + + Place it as a single top-level line directly after the license header block and + before the `package` statement. This keeps the marker file-level, greppable, and out of + generated KDoc. +- PR titles should follow conventional commits with component scope (e.g. `fix(cli): ...`); see + `CONTRIBUTING.md` for the full format. + +## Related instructions +- Copilot-focused instructions: `.github/copilot-instructions.md` +- Contribution details: `CONTRIBUTING.md` + +## Maintainer note — keeping this file effective +Internal guidance for whoever edits this file (not runtime rules for agents): +- Keep it short, structured, and imperative. +- Prefer concrete project facts and runnable commands over generic advice. +- Avoid duplicating content from `CONTRIBUTING.md` or subproject `AGENTS.md`; link or defer instead. +- Add examples only when they clarify a non-obvious rule. +- When changing rules here, check whether `.github/copilot-instructions.md` and the subproject + `AGENTS.md` files still align. diff --git a/cli/AGENTS.md b/cli/AGENTS.md new file mode 100644 index 00000000..3b94e3da --- /dev/null +++ b/cli/AGENTS.md @@ -0,0 +1,34 @@ +# AGENTS.md (cli) + +This file applies to `cli/`. Also read the repository-level `../AGENTS.md` for global rules. + +## Scope +- Thin Kotlin/JVM CLI wrapper over `watermarker-jvm`. +- Main entry point: `src/main/kotlin/Main.kt`. + +## Dependency and build flow +- `cli/` depends on local Maven publication from `watermarker/`. +- Always run this first when library changes are involved: + - `cd ../watermarker && ./gradlew publishToMavenLocal` +- If dependency resolution fails for `watermarker-jvm`, publish local artifacts and retry. + +## Dev environment and commands +- Use JDK 21 and the local wrapper from this folder. +- Commands: + - `./gradlew ktlintCheck` (mandatory before finishing changes) + - `./gradlew test` + - `./gradlew shadowJar` — produces `build/libs/cli--all.jar` + - `./gradlew run --args="--help"` +- Before finishing CLI changes, at minimum run `./gradlew ktlintCheck` and `./gradlew test`. + +## Implementation conventions +- Keep CLI behavior thin and delegate watermarking logic to `watermarker-jvm`. +- Avoid duplicating core algorithm logic in CLI. +- Follow existing option/argument style in `Main.kt` and keep UX consistent. + +## Testing and quality +- CLI testing is optional today, not mandatory. +- Add or adjust tests for changed CLI behavior when practical, especially for larger behavior changes. +- At minimum, validate the affected CLI flow manually or with the existing Gradle test/run commands. +- Keep diffs focused and avoid unrelated formatting churn. +- If user-facing CLI behavior changes, update docs under `docs/docs/03-usage/11-cli/`. diff --git a/docs/AGENTS.md b/docs/AGENTS.md new file mode 100644 index 00000000..fc7900b5 --- /dev/null +++ b/docs/AGENTS.md @@ -0,0 +1,35 @@ +# AGENTS.md (docs) + +This file applies to `docs/`. Also read the repository-level `../AGENTS.md` for global rules. + +## Scope +- Docusaurus 3 documentation site for all Innamark subprojects. +- This is not a Gradle project. + +## Dev environment and commands +- Use Node 18 and yarn. +- Run from `docs/`: + - `yarn install --frozen-lockfile` + - `yarn start` + - `yarn build` +- Matching CI workflows: `.github/workflows/test_docusaurus.yml`, + `.github/workflows/deploy_docusaurus.yml`. + +## Content structure rules +- Keep numbered, kebab-case paths and filenames. +- Relevant roots: + - `docs/docs/03-usage/` + - `docs/docs/04-development/` +- Add new docs with the next sequential number; do not renumber existing files unless required. + +## Update policy +- Any user-facing behavior change in `watermarker/`, `cli/`, or `webinterface/` should be reflected here. +- Keep examples and command snippets consistent with current build/test workflows. + +## Assets and licensing +- New non-source assets (images and other binary files) require a sibling `.license` file + per REUSE (e.g. `my-figure.jpg.license` for `my-figure.jpg`). + +## Quality +- Prefer small, focused docs diffs. +- Keep terminology aligned with the implementation and the watermarking algorithm. diff --git a/watermarker/AGENTS.md b/watermarker/AGENTS.md new file mode 100644 index 00000000..d739bfcc --- /dev/null +++ b/watermarker/AGENTS.md @@ -0,0 +1,80 @@ +# AGENTS.md (watermarker) + +This file applies to `watermarker/`. Also read the repository-level `../AGENTS.md` for global rules. + +## Scope +- Core Kotlin Multiplatform watermarking library (`commonMain`, `jvmMain`, `jsMain`). +- This is the canonical implementation used by both `cli/` and `webinterface/`. + +## Dev environment and commands +- Use JDK 21 and the local wrapper from this folder. +- Main commands: + - `./gradlew ktlintCheck` + - `./gradlew allTests` + - `./gradlew build` — canonical pre-finish check (runs `ktlintCheck` + tests). + - `./gradlew publishToMavenLocal` +- If downstream projects are touched (`cli/`, `webinterface/`), publish locally first. + +## Architecture map +- Core text algorithm: + - `src/commonMain/kotlin/watermarkers/text/PlainTextWatermarker.kt` + - `src/commonMain/kotlin/watermarkers/text/TextWatermarker.kt` +- Watermark/tag types: + - `src/commonMain/kotlin/types/watermarks/` +- Value-based responses: + - `src/commonMain/kotlin/types/responses/` +- JVM file integrations: + - `src/jvmMain/kotlin/watermarkers/file/` + - `src/jvmMain/kotlin/utils/FileHandling.kt` +- Platform-specific utils: + - JVM: `src/jvmMain/kotlin/utils/` + - JS: `src/jsMain/kotlin/utils/` + +## Core algorithm constraints (do not break) +- `PlainTextWatermarker` must reject covers that already contain alphabet chars or separator char + (alphabet: `\u2008`, `\u2009`, `\u202F`, `\u205F`; separator: `\u2004`). +- Capacity is driven by regular spaces only. +- Repeated embedding with separator delimiters is intentional robustness behavior. +- Keep JVM/JS/common behavior aligned so generated watermarks are interoperable. + +## Implementation conventions +- Use `InnamarkTagBuilder` by default for new watermark creation flows. +- Use value-based error handling in library code (`Status`, `Result`, `appendStatus`, `prependStatus`). +- For new custom events, subclass `Event.Warning` or `Event.Error`, set `source`, and implement `getMessage()`. +- Do not throw exceptions in core library paths unless there is an existing established exception boundary. + +## File type support (JVM only) +- For new watermarkable file types: + 1. Implement `WatermarkableFile`. + 2. Implement matching `FileWatermarker`. + 3. Register extension in `SupportedFileType` in `src/jvmMain/kotlin/utils/FileHandling.kt`. +- Do not extend deprecated `ZipFileWatermarker`. + +## Testing expectations +- `watermarker/` should always aim to be fully tested; this is the best-covered subproject in the repo. +- Before finishing watermarker changes, run from this folder: + - `./gradlew build` (canonical; runs `ktlintCheck` + all tests) + - or, for faster inner-loop iteration: `./gradlew ktlintCheck` plus `./gradlew jvmTest` / + `./gradlew jsTest` / `./gradlew allTests` +- Add/update tests in the correct target and level: + - `commonTest`, `jvmTest`, `jsTest` + - unit/integration where appropriate +- Current JVM test layout mirrors production packages and then splits into `unitTest/` and + `integrationTest/` directories, for example: + - `src/jvmTest/kotlin/types/files/unitTest/` + - `src/jvmTest/kotlin/types/files/integrationTest/` + - `src/jvmTest/kotlin/watermarkers/file/unitTest/` + - `src/jvmTest/kotlin/watermarkers/file/integrationTest/` +- Follow existing class naming patterns: + - shared/general tests often use `*Test` + - JVM-specific tests often use `*TestJvm` + - integration tests use `*IntegrationTest` or `*IntegrationTestJvm` +- Follow existing test function naming style: lowercase names with underscores that describe + operation, condition, and expected result, for example `addWatermark_valid_success`, + `fromFile_invalidPath_error`, or `decode_encode_inversion`. +- Keep the current `Arrange` / `Act` / `Assert` structure used in existing tests. +- Use `src/jvmTest/resources/` for stable JVM test fixtures and reuse representative files from + `samples/` for file-based scenarios when they already match the intended behavior. +- The `samples/` directory contains important text and zip examples for file-oriented watermarking + cases; prefer reusing those scenarios over inventing new binary fixtures. +- Do not regenerate or modify existing binary fixtures unintentionally. diff --git a/webinterface/AGENTS.md b/webinterface/AGENTS.md new file mode 100644 index 00000000..02312e03 --- /dev/null +++ b/webinterface/AGENTS.md @@ -0,0 +1,45 @@ +# AGENTS.md (webinterface) + +This file applies to `webinterface/`. Also read the repository-level `../AGENTS.md` for global rules. + +## Scope +- Kotlin/JS KVision frontend consuming multiplatform `watermarker` artifacts. +- Main UI code lives in `src/jsMain/kotlin/`. + +## Dependency and build flow +- `webinterface/` depends on local `watermarker` publication. +- Precondition when library changes are involved: + - `cd ../watermarker && ./gradlew publishToMavenLocal` + +## Dev environment and commands +- Use JDK 21 and the local wrapper from this folder. +- Run from `webinterface/`: + - `./gradlew ktlintCheck` (mandatory before finishing changes) + - `./gradlew test` + - `./gradlew -t run` + - `./gradlew clean zip` +- Docker path validated in CI: + - `docker build -t innamark-webinterface -f webinterface/Dockerfile .` +- Newcomer fast-start from repo root: + - `docker compose up` using `../docker-compose.yml` (builds and serves the webinterface path). +- Before finishing changes, at minimum run `./gradlew ktlintCheck` and `./gradlew test`. + +## UI behavior constraints +- Keep the two active text tabs functionally correct: + - Embed tab lets users check if a watermark fits the cover text, choose `InnamarkTag` + configurations (for example CRC32, SHA3, compression/size), and embed the watermark into + the cover text. + - Extract tab lets users extract watermark content from an existing watermarked cover text. +- Preserve capacity logic based on `PlainTextWatermarker.getMinimumInsertPositions(...)`. +- Keep the tab-specific UX with separate text input/textarea fields for embed and extract flows. +- Keep behavior aligned with library constraints (space-based capacity, alphabet/separator handling). + +## Versioning caution +- Do not casually change pinned Kotlin/KVision versions in `gradle.properties`. +- KVision is version-sensitive to Kotlin; upgrades should be explicit and validated. + +## Testing and docs +- Webinterface testing is optional today, not mandatory. +- Add or update JS tests for behavior changes when practical, especially for non-trivial UI logic. +- At minimum, validate changed flows in the dev server or docker-based fast-start path when feasible. +- If user-facing UI behavior changes, update docs under `docs/docs/03-usage/12-webinterface/`.