Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
75a6283
feat(core): first executable invariants of the clipboard core
rgdevment Sep 13, 2026
c6ab2ec
refactor(core): make the format catalogue platform-neutral
rgdevment Sep 13, 2026
d13561d
feat(core): seal the clipboard watcher with properties and mutation t…
rgdevment Sep 13, 2026
ee64c02
feat(mac): capture a full item from the real pasteboard
rgdevment Sep 13, 2026
ede189d
feat(store): schema, search that actually works, and the broken-item …
rgdevment Sep 13, 2026
754e6cd
feat(mac): permission probes and per-layout keycode resolution
rgdevment Sep 13, 2026
63e9e67
test: raise the core to 97% coverage and prove privacy against the sy…
rgdevment Sep 13, 2026
58cacc1
feat(store): rebuild the schema on what 2.x learned in production
rgdevment Sep 13, 2026
e15886e
feat(mac): track the paste destination without observers
rgdevment Sep 13, 2026
540081f
feat(mac): complete the paste sequence and turn the harness into a ba…
rgdevment Sep 13, 2026
4c58ff9
fix: declare BSL-1.0 and stop caching the keycode
rgdevment Sep 13, 2026
1778b92
feat(core): recover the full content classification from 2.x
rgdevment Sep 13, 2026
270560a
fix: close the six blockers the audit found
rgdevment Sep 14, 2026
672b8f6
feat(mac): read the text inside images so captures become searchable
rgdevment Sep 14, 2026
1d62ecd
feat(store): the history finally survives closing the application
rgdevment Sep 14, 2026
0aa8f07
feat(store): metadata, work queue, blob store, listing and retention
rgdevment Sep 14, 2026
086e050
feat: thumbnails and media metadata close the macOS core
rgdevment Sep 14, 2026
6f27750
feat: plain-text paste stops mutilating the item, and copying stops
rgdevment Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ jobs:
- run: cargo fmt --all -- --check
- run: cargo clippy --workspace --all-targets -- -D warnings
- run: cargo test --workspace
# El ciclo real contra el portapapeles del sistema. No cabe en cargo
# test porque NSPasteboard exige el hilo principal y el runner no lo
# garantiza.
- run: cargo run -p cp-mac --example probe

deny:
name: Dependency audit
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/commits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ jobs:
if ! printf '%s' "$subject" | grep -qE "$pattern"; then
echo "no sigue la convencion: $subject"; fail=1
fi
done < <(git rev-list origin/${{ github.base_ref }}..HEAD)
done < <(git rev-list --no-merges origin/${{ github.base_ref }}..HEAD)
exit $fail
49 changes: 46 additions & 3 deletions .github/workflows/rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:

- name: No voseo in the Spanish anywhere
run: |
if grep -rniE '\b(vos|tenes|queres|podes|anda|mira|hace|che)\b' \
if grep -rniE '\b(vos|tenés|querés|podés|andá|mirá|hacé|che)\b' \
crates docs README.md --include='*.rs' --include='*.md' 2>/dev/null; then
echo "espanol neutro, sin voseo"; exit 1
fi
Expand All @@ -58,8 +58,9 @@ jobs:

- name: No prose blocks in the code
run: |
if awk '/^\s*\/\/[^\/]/{n++; if (n>3) {print FILENAME": bloque de prosa"; exit 1}} !/^\s*\/\//{n=0}' \
$(find crates -name '*.rs'); then :; else exit 1; fi
awk '/^[ \t]*\/\/[^\/!]/ { n++; if (n > 3) { print FILENAME":"NR": bloque de prosa"; bad = 1 }; next }
{ n = 0 }
END { exit bad }' $(find crates -name '*.rs')

deterministic:
name: Tests are deterministic
Expand All @@ -70,3 +71,45 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: Twenty consecutive runs of the core
run: for i in $(seq 1 20); do cargo test -p cp-core --quiet || exit 1; done

mutants:
name: The suite kills every mutant
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-mutants
# Una prueba que pasa contra un núcleo mutado no está probando nada. El
# criterio de aceptación de la Etapa 0 es exactamente este: la batería
# tiene que fallar contra una implementación que no sepa lo que sabemos.
- run: cargo mutants -p cp-core -p cp-store --no-times

coverage:
name: Coverage does not slip
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-llvm-cov
# El arnés entra en la medición: sin él, todo el código de plataforma
# aparece a cero y el número miente en las dos direcciones.
- run: cargo llvm-cov --no-report --workspace
- run: cargo llvm-cov --no-report run -p cp-mac --example probe
- run: cargo llvm-cov report --fail-under-lines 90 --summary-only

budget:
name: Latency stays within budget
runs-on: macos-15
env:
CP_BUDGET_SLACK: "4"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
# Busca regresiones de orden de magnitud —una consulta que deja de usar
# el índice—, no microsegundos. Por eso corre en release y con holgura.
- run: cargo run -p cp-store --release --example budget
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/target
**/*.rs.bk
.DS_Store
/mutants.out
/mutants.out.old
44 changes: 28 additions & 16 deletions CLA.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Contributor License Agreement

CopyPaste Individual Contributor License Agreement, version 1.1.
CopyPaste Individual Contributor License Agreement, version 1.2.

Thank you for contributing to CopyPaste. This agreement exists for one reason:
CopyPaste is released under the GPL-3.0 **and** offered under separate
commercial terms to organisations that cannot comply with the GPL. Offering
those commercial terms requires the right to license the whole codebase that
way — including your contribution. Without this agreement from every
contributor, that right does not exist and the dual model collapses.
[commercial terms](COMMERCIAL.md) to organisations that cannot comply
with the GPL. Offering those commercial terms requires the right to license
the whole codebase that way — including your contribution. Without this
agreement from every contributor, that right does not exist and the dual model
collapses.

You keep the copyright on everything you write. This is a licence you grant,
not a transfer of ownership.
Expand All @@ -26,15 +27,19 @@ modification to or addition to an existing work, that You intentionally submit
to this project for inclusion in it. "Submit" means any form of electronic,
verbal, or written communication sent to the project or its maintainers,
including but not limited to Pull Requests, issues, patches, and code
suggestions made during review — excluding
any communication you conspicuously mark "Not a Contribution".
suggestions made during review — excluding any communication you
conspicuously mark "Not a Contribution".

This agreement covers every Contribution You submit after signing **and every
one You submitted before**. Code reaches a project by more routes than a Pull
Request, and a signature that only looked forward would leave those earlier
routes unaccounted for.

**"Project Owner"** means Mario Hidalgo G. (rgdevment), the copyright holder
and maintainer of CopyPaste.
and maintainer of CopyPaste, and whoever holds those rights after him — a
successor, or anyone the project is assigned or transferred to, in whole or in
part. The licences You grant below run to them on the same terms, and to no
wider ones.

## 2. Copyright licence

Expand All @@ -47,9 +52,10 @@ Contribution and such derivative works.
**Including under licences other than the GPL-3.0.** This is the clause that
makes commercial licensing possible; it is stated explicitly so nobody has to
infer it from the word "sublicense".

It also covers **distributing signed binaries through application stores**,
whose terms of service are not compatible with the licence this project uses.
The source stays available either way; what needs separate terms is the
whose terms of service are not compatible with the GPL-3.0. The source stays
available under the GPL-3.0 either way; what needs separate terms is the
compiled build that a store hands to its users.

**Moral rights.** To the fullest extent permitted by the law that applies to
Expand Down Expand Up @@ -124,6 +130,12 @@ mandatory law where You live.
**If a clause fails.** If any provision is held unenforceable, the rest stays
in force and that provision is read as narrowly as needed to make it valid.

**This agreement travels with the project.** The Project Owner may assign it,
together with the rights it grants, to whoever the project passes to. You need
not be asked, and nothing about what You granted changes: what a successor
receives is what You gave, neither more nor less. You keep the copyright on
everything You wrote, and section 6 binds them as it binds him.

**This is the whole agreement** between You and the Project Owner about Your
Contributions, and it replaces anything discussed before it. A later version
of this document applies only to Contributions You submit after signing that
Expand All @@ -144,13 +156,13 @@ I have read the CLA Document and I hereby sign the CLA
You sign once. Every later Pull Request from the same GitHub account is
covered automatically.

This signature covers CopyPaste only. Other projects by the same owner have
their own agreement and their own signature record.
This signature covers CopyPaste only. Other projects by the same owner have their
own agreement and their own signature record.

## If you would rather not sign

That is a legitimate choice, and it costs you nothing else in this project.
You can still use CopyPaste, report bugs, request features, help with
translations feedback, discuss design, package it for your distribution, and
fork the project under the GPL-3.0. Only merging code into this repository
requires the agreement.
You can still use CopyPaste, report bugs, request features, discuss design,
package it for your distribution, help with translations, and fork the project
under the GPL-3.0. Only merging code into this repository requires the
agreement.
Loading
Loading