Skip to content
This repository was archived by the owner on Nov 12, 2026. It is now read-only.

Commit 015a368

Browse files
authored
Merge pull request #627 from techmore/freeze-app-copies
Freeze duplicate app copies; ownership table and CI guard (repo reorg phase 1)
2 parents d52a7d3 + 01e0f00 commit 015a368

35 files changed

Lines changed: 580 additions & 0 deletions

File tree

‎.github/workflows/frozen-paths.yml‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Frozen paths guard
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened, labeled, unlabeled]
6+
paths:
7+
- 'rust/**'
8+
- 'mseries/**'
9+
- '.github/workflows/frozen-paths.yml'
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
17+
18+
jobs:
19+
guard:
20+
name: Reject edits to frozen app copies
21+
runs-on: ubuntu-latest
22+
timeout-minutes: 5
23+
steps:
24+
- uses: actions/checkout@v7
25+
with:
26+
fetch-depth: 0
27+
- name: Guard tests
28+
run: python3 -B -m unittest discover -s mseries/ci -p 'test_check_frozen.py' -v
29+
- name: Check changed paths against mseries/ci/frozen-paths.txt
30+
env:
31+
BASE: ${{ github.event.pull_request.base.sha }}
32+
HEAD: ${{ github.event.pull_request.head.sha }}
33+
ALLOW: ${{ contains(github.event.pull_request.labels.*.name, 'allow-frozen-edit') && '--allow' || '' }}
34+
run: python3 mseries/ci/check_frozen.py $ALLOW "$BASE" "$HEAD"

‎AGENTS.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
> reload or recovery from a confirmed panel defect, and state when code is installed but not yet loaded. Record the pin,
2525
> what you re-verified and what is still unverified in `mseries/OS9-HANDOFF.md`.
2626
27+
- **One source of truth per app:** SDK crates and apps (`rust/msdk*`, `rust/mseries-*` except the compositor,
28+
`mseries/sdk-*`, `battery`, `phone-setup`, `polybagger-print-manager`, `messages-mcp` and more) are edited in
29+
[techmore/mseries-sdk-apps](https://github.com/techmore/mseries-sdk-apps). The copies here are frozen snapshots
30+
(`FROZEN.md` in each dir); CI rejects PR edits unless labeled `allow-frozen-edit`. Table and full list:
31+
[mseries/REPO-OWNERSHIP.md](mseries/REPO-OWNERSHIP.md).
2732
- Keep `mseries/OS9-HANDOFF.md`, `mseries/ROADMAP.md`, and relevant public
2833
status pages current as work lands. Record concrete changes, commands,
2934
verification results, blockers, and the next task.

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# elementary OS for Apple Silicon (M-series)
22

3+
> **Source of truth for apps:** the Rust Pantheon SDK and first-party apps are edited in
4+
> [techmore/mseries-sdk-apps](https://github.com/techmore/mseries-sdk-apps); their copies here are frozen
5+
> snapshots guarded by CI. See [mseries/REPO-OWNERSHIP.md](mseries/REPO-OWNERSHIP.md).
6+
37
elementary OS 9 on an M1/M2-family Mac, alongside macOS: Asahi Alarm as the boot
48
layer, elementary (Pantheon) as the system you use, installed with one command,
59
full-disk encryption included. Modelled on [omarchy-mac](https://github.com/omarchy-mac/omarchy-mac),

‎mseries/REPO-OWNERSHIP.md‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Repository ownership (phase 1: one writable source per app)
2+
3+
Status 2026-10-27. Implements the first step of [REPOSITORY-TOPOLOGY.md](REPOSITORY-TOPOLOGY.md):
4+
apps now live in [`techmore/mseries-sdk-apps`](https://github.com/techmore/mseries-sdk-apps)
5+
(compared at `origin/main` `40d4445c4414e83da5893500528e088ec599af30`). The OS repo still
6+
holds older duplicate copies. Those are now **frozen migration snapshots**: nothing is
7+
deleted, moved or archived, but PRs that edit them fail the `Frozen paths guard` CI check
8+
(label `allow-frozen-edit` overrides). The guarded list is
9+
[`ci/frozen-paths.txt`](ci/frozen-paths.txt); each frozen directory has a `FROZEN.md`.
10+
Branch rules: [BRANCHING.md](BRANCHING.md).
11+
12+
Method: real trees compared with `diff -rq` between `git archive origin/main` of the SDK repo
13+
and this checkout (`dev` at `7478f2fe`). Phase 2 (kernel split) is owned by another session;
14+
Kernel rows are only tagged.
15+
16+
## Apps already owned by the SDK repo (frozen here)
17+
18+
| Path in OS repo | SDK repo state |
19+
| --- | --- |
20+
| `rust/claude-pantheon-rs` | **Newer** in SDK (plugin registry; 6 files only in SDK, 7 changed) |
21+
| `rust/mseries-messages` | **Newer** in SDK (Signal channel, `signal.rs`; 5 files changed) |
22+
| `rust/mseries-pantheon-kit` | **Newer** in SDK (diff timeline, `timeline.rs`; `lib.rs` changed) |
23+
| `mseries/battery` | One test file differs (`test_battery_enhance.py`); reconcile in SDK |
24+
| `mseries/diskspace-app` | Identical except `test.sh` |
25+
| `mseries/phone-setup` | Identical (SDK tree has a stray `__pycache__`; remove there) |
26+
| `rust/granite-smoke`, `msdk`, `msdk-gtk`, `mseries-ai`, `mseries-apple-dev`, `mseries-broker`, `mseries-diskspace`, `mseries-dock`, `mseries-greeter`, `mseries-power`, `mseries-reply`, `mseries-signal-import`, `mseries-system-monitor`, `mseries-update-core`, `mseries-updates` | Identical |
27+
| `mseries/sdk-tests`, `sdk-bench`, `sdk-status-host`, `messages-mcp`, `polybagger-print-manager`, `updates-app`, `fleet-shepherd` | Identical |
28+
| Docs: `APP-BUILDING-GUIDE.md`, `DOCK-SDK-SPEC.md`, `RUST-PANTHEON-SDK.md`, `RUST-PANTHEON-CLIENTS.md`, `SDK-*.md` (13 files) | Identical (guarded by path; no banner added) |
29+
30+
Caveats: `mseries-update-core` still bundles the OS-owned root helper with the app-facing
31+
contract, and `mseries-power` backs the OS power policy. Both are frozen per the plan; use the
32+
label for helper/policy changes until the contract split in REPOSITORY-TOPOLOGY.md lands.
33+
Also identical but not frozen (decide in later phases): `BATTERY-ETA.md`, `BATTERY-PROFILER.md`,
34+
`MESSAGES-PARITY.md`, `MESSAGING-STATUS.md`, `install-battery*.sh`, `install-phone-setup.sh`,
35+
`install-messaging-bluez.sh`.
36+
37+
## SDK-only (nothing to freeze here)
38+
39+
`rust/mseries-image-studio`, `mseries/image-studio`, `rust/torrential`. In flight: Signal Pantheon as
40+
`mseries/signal-pantheon` (SDK PR #14). SDK `rust/Cargo.toml` lists `mseries-image-studio` and
41+
drops `pantheon-compositor`; the OS workspace keeps the compositor, so the two `Cargo.toml` /
42+
`Cargo.lock` files are intentionally independent and not frozen.
43+
44+
## Exists only in the OS repo: candidates to import (not imported now)
45+
46+
| Path | Note |
47+
| --- | --- |
48+
| `mseries/claude-pantheon-native` | C/Meson client; SDK has the Rust `claude-pantheon-rs` only |
49+
| `mseries/torrential-native`, `mseries/TORRENTIAL-PORT.md` | SDK imported `rust/torrential` with history (#15); confirm what native/port material is still needed |
50+
| `mseries/signal-wingpanel`, `signal-launcher.sh`, `install-signal*.sh`, `SIGNAL-PANTHEON-DESIGN.md` | Signal Pantheon moves with SDK PR #14; deferred per MESSAGING-STATUS.md |
51+
| `mseries/smart-reply`, `SMART-REPLY-DESIGN.md`, `install-smart-reply.sh` | Pairs with `rust/mseries-reply` |
52+
| `mseries/tether`, `TETHER-CONTINUITY.md`, `omdrop*`, `orchard*`, `horizon-rdp`, `opencode-desktop` | Standalone apps; classification needs an owner decision |
53+
54+
## Classification of the rest of `rust/` and `mseries/`
55+
56+
| Class | Paths |
57+
| --- | --- |
58+
| OS (stays) | `rust/pantheon-compositor` (SDK keeps only the vendored protocol XML; its drift check treats this repo as source of truth), `pantheon-rust-compositor`, `gala-*`, `window-*`, `dock-*`, `docked-lid`, `quick-settings`, `panel*`, `wingpanel-tests`, `*-wingpanel` and `install-*wingpanel*` (clockright, codexbar, repobar, share-eyes, t3, troubleshooter), `codexbar*`, `repobar*`, `theme`, `desktop-notifications`, `dark-mode`, `display-*`, `brightness`, `keyboard-backlight`, `audio`, `airplay`, `power`, `touchid-settings`, `icloud-passwords`, `image-actions`, `screenshot-shelf`, `work-mode`, `ui-scale`, `netspeed`, `update`, `releases`, `release`, `debs`, `packages.arm64`, `patches`, `customizations`, `minimal-system`, `enhance*`, `user-enhance.sh`, `post-install.sh`, `validate.sh`, `ci`, remaining `install-*.sh`, `lib-*.sh`, `test-*`, `machine-lab`, `vms`, `muvm-source.sh`, `modrun.py`, `maintenance`, `procedures`, `tools` |
59+
| Kernel (phase 2, other session) | `aurora`, `aurora-sep`, `aurora-touchid*`, `AURORA-SECOND-BOOT.md`, `boot`, `fairydust`, `hardware`, `lid-trace`, `KERNEL-*.md`, `check-kernel-config.py`, `test-kernel-config.py`, `install-initramfs-crossbar.sh`, `install-boot-isolation.sh`, `USB-C-DOCK-DP-ALT-MODE.md`, `FIRMWARE-WIFI.md`, `upstream`, `upstreams`, `upstream-audits`, `UPSTREAM-PINS.md` |
60+
| Hub / docs | All other top-level `*.md` (ROADMAP, OS9-HANDOFF, BRANCHING, REPOSITORY-TOPOLOGY, PORT-MAP, audits, designs, runbooks), `receipts`, `benchmarks`, `local-ai`, `dictation`, `docs/` and the Pages site |
61+
62+
The Kernel and OS lists are grouped by name and judgment, not by exhaustive file audit; items
63+
that fall between classes should be settled in phase 2 or later.
64+
65+
## Where to edit
66+
67+
| You are changing | Edit in |
68+
| --- | --- |
69+
| Anything listed under "already owned by the SDK repo" | `techmore/mseries-sdk-apps` |
70+
| Compositor, panel, installers, packaging, OS services | this repo |
71+
| Kernel/boot | this repo until phase 2 lands |
72+
73+
Cutover revision recorded in every `FROZEN.md`: `mseries-sdk-apps@40d4445c4414e83da5893500528e088ec599af30`.

‎mseries/battery/FROZEN.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# FROZEN: edit in mseries-sdk-apps
2+
3+
The writable source of truth for this directory is
4+
[`techmore/mseries-sdk-apps`](https://github.com/techmore/mseries-sdk-apps) at `mseries/battery`.
5+
This copy is a frozen migration snapshot kept for rollback and reference
6+
(see [REPOSITORY-TOPOLOGY.md](/mseries/REPOSITORY-TOPOLOGY.md), staged transition step 5).
7+
8+
- Cutover revision: `mseries-sdk-apps@40d4445c4414e83da5893500528e088ec599af30` (origin/main, 2026-10-27)
9+
- State at cutover: one test file (test_battery_enhance.py) differs; reconcile in the SDK repo
10+
- Make changes in `mseries-sdk-apps`, not here. A PR that edits this directory fails the
11+
`Frozen paths guard` check unless it carries the `allow-frozen-edit` label.
12+
- Nothing here has been deleted or moved. Ownership table: [REPO-OWNERSHIP.md](/mseries/REPO-OWNERSHIP.md).

‎mseries/ci/check_frozen.py‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
"""Fail when a change touches a path whose source of truth moved to mseries-sdk-apps.
3+
4+
Usage: check_frozen.py [--allow] BASE HEAD
5+
Paths come from mseries/ci/frozen-paths.txt. FROZEN.md files are exempt.
6+
--allow (the `allow-frozen-edit` label) reports the hits but exits 0.
7+
"""
8+
from pathlib import Path
9+
import subprocess
10+
import sys
11+
12+
ROOT = Path(__file__).resolve().parents[2]
13+
MANIFEST = ROOT / 'mseries/ci/frozen-paths.txt'
14+
15+
16+
def frozen_paths():
17+
lines = (line.strip() for line in MANIFEST.read_text().splitlines())
18+
return [line.rstrip('/') for line in lines if line and not line.startswith('#')]
19+
20+
21+
def is_frozen(path, frozen):
22+
if path.rsplit('/', 1)[-1] == 'FROZEN.md':
23+
return False
24+
return any(path == f or path.startswith(f + '/') for f in frozen)
25+
26+
27+
def hits(changed, frozen):
28+
return sorted(p for p in changed if is_frozen(p, frozen))
29+
30+
31+
def changed_files(base, head):
32+
# --no-renames lists both sides of a rename, so a move out of a frozen dir is caught.
33+
out = subprocess.run(
34+
['git', 'diff', '--name-only', '--no-renames', f'{base}...{head}'],
35+
cwd=ROOT, check=True, capture_output=True, text=True).stdout
36+
return out.splitlines()
37+
38+
39+
def main(argv):
40+
allow = '--allow' in argv
41+
args = [a for a in argv if a != '--allow']
42+
if len(args) != 2:
43+
print(__doc__, file=sys.stderr)
44+
return 2
45+
found = hits(changed_files(*args), frozen_paths())
46+
if not found:
47+
print('No frozen paths modified.')
48+
return 0
49+
print('Frozen paths modified (source of truth: techmore/mseries-sdk-apps):')
50+
for path in found:
51+
print(f' {path}')
52+
if allow:
53+
print('Label allow-frozen-edit is set; allowing.')
54+
return 0
55+
print('::error::Edit these in techmore/mseries-sdk-apps, or add the '
56+
'`allow-frozen-edit` label to this PR. See mseries/REPO-OWNERSHIP.md.')
57+
return 1
58+
59+
60+
if __name__ == '__main__':
61+
sys.exit(main(sys.argv[1:]))

‎mseries/ci/frozen-paths.txt‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Paths whose writable source of truth is techmore/mseries-sdk-apps.
2+
# One repo-relative path per line; a directory covers everything below it.
3+
# See mseries/REPO-OWNERSHIP.md. FROZEN.md files are exempt from the guard.
4+
rust/granite-smoke
5+
rust/claude-pantheon-rs
6+
rust/msdk
7+
rust/msdk-gtk
8+
rust/mseries-ai
9+
rust/mseries-apple-dev
10+
rust/mseries-broker
11+
rust/mseries-diskspace
12+
rust/mseries-dock
13+
rust/mseries-greeter
14+
rust/mseries-messages
15+
rust/mseries-pantheon-kit
16+
rust/mseries-power
17+
rust/mseries-reply
18+
rust/mseries-signal-import
19+
rust/mseries-system-monitor
20+
rust/mseries-update-core
21+
rust/mseries-updates
22+
mseries/sdk-tests
23+
mseries/sdk-bench
24+
mseries/sdk-status-host
25+
mseries/phone-setup
26+
mseries/battery
27+
mseries/polybagger-print-manager
28+
mseries/messages-mcp
29+
mseries/diskspace-app
30+
mseries/updates-app
31+
mseries/fleet-shepherd
32+
mseries/APP-BUILDING-GUIDE.md
33+
mseries/DOCK-SDK-SPEC.md
34+
mseries/RUST-PANTHEON-SDK.md
35+
mseries/RUST-PANTHEON-CLIENTS.md
36+
mseries/SDK-AGENT-SURFACE.md
37+
mseries/SDK-AUDIT-2026-10-23.md
38+
mseries/SDK-COMPATIBILITY.md
39+
mseries/SDK-COMPLETION.md
40+
mseries/SDK-CORNERS.md
41+
mseries/SDK-DESIGN-LANGUAGE.md
42+
mseries/SDK-GOLDEN-PATH.md
43+
mseries/SDK-INTROSPECTION-AND-STREAMING.md
44+
mseries/SDK-PARITY.md
45+
mseries/SDK-RUNTIME-CONTRACT.md
46+
mseries/SDK-USAGE-DATA.md

‎mseries/ci/test_check_frozen.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import unittest
2+
3+
import check_frozen as cf
4+
5+
FROZEN = ['rust/msdk', 'mseries/SDK-PARITY.md']
6+
7+
8+
class FrozenTests(unittest.TestCase):
9+
def test_hits_and_exemptions(self):
10+
changed = ['rust/msdk/src/lib.rs', 'rust/msdk-gtk/a.rs', 'rust/msdk/FROZEN.md',
11+
'mseries/SDK-PARITY.md', 'mseries/ROADMAP.md']
12+
self.assertEqual(cf.hits(changed, FROZEN),
13+
['mseries/SDK-PARITY.md', 'rust/msdk/src/lib.rs'])
14+
15+
def test_manifest_paths_exist(self):
16+
for path in cf.frozen_paths():
17+
self.assertTrue((cf.ROOT / path).exists(), path)
18+
19+
20+
if __name__ == '__main__':
21+
unittest.main()

‎mseries/diskspace-app/FROZEN.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# FROZEN: edit in mseries-sdk-apps
2+
3+
The writable source of truth for this directory is
4+
[`techmore/mseries-sdk-apps`](https://github.com/techmore/mseries-sdk-apps) at `mseries/diskspace-app`.
5+
This copy is a frozen migration snapshot kept for rollback and reference
6+
(see [REPOSITORY-TOPOLOGY.md](/mseries/REPOSITORY-TOPOLOGY.md), staged transition step 5).
7+
8+
- Cutover revision: `mseries-sdk-apps@40d4445c4414e83da5893500528e088ec599af30` (origin/main, 2026-10-27)
9+
- State at cutover: identical except test.sh
10+
- Make changes in `mseries-sdk-apps`, not here. A PR that edits this directory fails the
11+
`Frozen paths guard` check unless it carries the `allow-frozen-edit` label.
12+
- Nothing here has been deleted or moved. Ownership table: [REPO-OWNERSHIP.md](/mseries/REPO-OWNERSHIP.md).

‎mseries/fleet-shepherd/FROZEN.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# FROZEN: edit in mseries-sdk-apps
2+
3+
The writable source of truth for this directory is
4+
[`techmore/mseries-sdk-apps`](https://github.com/techmore/mseries-sdk-apps) at `mseries/fleet-shepherd`.
5+
This copy is a frozen migration snapshot kept for rollback and reference
6+
(see [REPOSITORY-TOPOLOGY.md](/mseries/REPOSITORY-TOPOLOGY.md), staged transition step 5).
7+
8+
- Cutover revision: `mseries-sdk-apps@40d4445c4414e83da5893500528e088ec599af30` (origin/main, 2026-10-27)
9+
- State at cutover: identical to the SDK copy
10+
- Make changes in `mseries-sdk-apps`, not here. A PR that edits this directory fails the
11+
`Frozen paths guard` check unless it carries the `allow-frozen-edit` label.
12+
- Nothing here has been deleted or moved. Ownership table: [REPO-OWNERSHIP.md](/mseries/REPO-OWNERSHIP.md).

0 commit comments

Comments
 (0)