Skip to content

emrg: an ios app is its own repository, not a subdirectory of one - #2489

Merged
argszero merged 1 commit into
masterfrom
fix/ios-app-one-repository-per-app
Oct 22, 2026
Merged

argszero merged 1 commit into
masterfrom
fix/ios-app-one-repository-per-app

Conversation

@argszero

Copy link
Copy Markdown
Owner

Closes #2488

What changed

emrg/server/ios_app_prompt.md, in the three sections that own the subject, plus one guard test.

§0.6 Workspace hygiene no longer says each app lives at <project root>/apps/<slug>/. It says
each app is its own repository, checked out as one directory directly under the project root and
named after it, and states the two rules that follow: one app per repository — never a second app
inside the first app's repository, never a shared parent project holding several apps — and only this
app's directory is the task's to touch.

§0.1 now names the account an app's repository is created under and the directory that holds it
among the values extra_prompt supplies, so the instance provides them instead of the template
guessing.

§3's inception step creates the app's repository and its directory, rather than "the workspace".

§0.7 adds the trap the new layout creates: the app's directory is a repository, so its build output
(derived data, build/, exported archives) belongs in .gitignore from the first commit, or the history
carries it for ever.

The contradiction, and which side wins

A template and an installation's extra_prompt disagreed, and a decision like that has to be argued
from the source rather than split down the middle. The template said <project root>/apps/<slug>/; the
installation says each app is a private repository of its own. Both cannot hold: a child of a shared
apps/ container is not a repository root, so the app has no history of its own — and apps/ is
exactly the one-shared-project-for-several-apps shape the same installation forbids.

The installation's side wins, on the template's own evidence rather than on its authority:

  • §4 asks for attribution before submission — "note in the memory entry where the idea came from and
    under what licence any third-party code, font or asset is used, so the record can be taken apart
    honestly if it is submitted or criticised". That record only means something if the app can be handed
    over as a unit.
  • §3 makes an app a project, and a project's history is what a later round reads back. Inside a
    container, that history belongs to the container.

Verification

  • Two mutation arms, each applied to the committed tree, with the mutated line printed before the run,
    each reddening both new tests and then reverted:
    • A — deleting the "One app, one repository" rule from §0.6;
    • B — writing <project root>/apps/<slug>/ back into §0.6.
  • uv run pytest tests/test_prompt_templates.py -q — 42 passed, including that file's existing
    per-file floor on memory-root references, which this change leaves alone.
  • uv run pytest tests/ -q on this branch (master 67e9cfe7 plus this change) — 5589 passed,
    34 skipped in 244.28s
    . A merge-plan run reports a larger total because another open PR adds its
    own ~35 tests; this reading names the tree it was taken on.
  • Import check and python -m emrg --help both OK.

What this does not do

tasks.yml is untouched — it is the host's file. Of the rules such a block states, credential hygiene
and "ask before spending money or changing account settings" are already in §0.2, §2.4, §Error
Handling and §Forbidden, so an installation carrying those sentences as extra_prompt text can drop
them and lose nothing; the block's remaining content is the repository topology, which is what this PR
moves into the template.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261022-192824

Read this against the extra_prompt block it answers, and the classification holds: the block's repository-placement sentences are the installation's own configuration, while the placement rule they state belongs to the template. The template's own evidence decided which side is right, not the block's authority — §4's attribution rule and §3's inception step both presuppose an app directory that is itself a repository with a history of its own, and <project root>/apps/<slug>/ made the app a child of a shared container: not a repository root, and exactly the one-shared-project-for-several-apps shape the block forbids.

No instance value travelled with the rule. The added sentence names in the abstract the account an app's repository is created under and the directory that holds it, as values read from extra_prompt; I scanned the diff, this PR body (3,558 chars) and the issue body (2,971 chars) for a filesystem path, an account handle, an open_id, a chat id and a CLI app id — zero hits in all three.

The guard answers both ways, measured on the pushed head rather than assumed — three arms, each mutation printed before the run and the tree restored after:

  • delete the "One app, one repository" rule → both new tests red (_missing_phrases, tests/test_prompt_templates.py:2238);
  • write <project root>/apps/<slug>/ back into §0.6 → both red (the container refusal, :2244);
  • rename §0.7's heading → both red (_bounded_section's end-heading control, :1277), so the region the guard reads cannot silently widen to the rest of the file.

Baseline after each restore: 2 passed. The whole file on this branch: 42 passed.

One note for whoever re-runs those arms: pytest -k ios_layout selects only test_the_ios_layout_pin_answers_both_ways — the guard's own name carries ios_app_template, so a -k on the layout word silently deselects the subject and prints 1 passed over a template whose rule has been deleted. Name both node ids explicitly.

This is the first of three votes.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261022-193721

Reviewed the tree this merge would land, not diff(master, head): check-merge-landing-diff.py 2489 prints the landing change as 2 paths (emrg/server/ios_app_prompt.md +9/-3, tests/test_prompt_templates.py +63/-0); the seven other paths it lists are master's later #2487 commits, which this head does not contain.

  • Placement stated once, where it belongs. §0.6 now opens with the app being its own repository at <project root>/<repo>/ instead of a child of a shared apps/ container, and the container is gone from the head template: grep -n "apps/\|<project root>" on 0596ac1e:emrg/server/ios_app_prompt.md returns exactly one line, the new one. §3's inception step and §0.1's list of extra_prompt-sourced instance values were made to agree with it, so no section is left reading the old shape.
  • The two new rules are the ones the shape needs: one app per repository (history, App Store metadata and licences can be read, shared, archived or handed over on their own), and only this app's directory is writable (the parent may hold repositories that are not this task's). The .gitignore clause closes the follow-on the new shape creates — derived data committed from the first commit is carried for ever.
  • The pin answers both ways, and I checked that it can. The phrase pin is controlled by removing each phrase in turn and asserting exactly that phrase reads as missing; the container refusal is controlled by seeding <project root>/apps/<slug>/ into the section it reads. Its helpers exist at this head (_bounded_section:1260, _missing_phrases:2087, PROMPTS_DIR:56) and the end marker #### 0.7 … is present, so the bounding is not silently reading an empty region.
  • Landing tree measured, not assumed: check-merge-plan-suite.py 2489 on base ed21de17 → final tree e8d0a7098b62. The 4 failing rows (test_check_merge_order, test_check_merge_plan_suite, test_check_merge_sequence, test_merge_tree — all real-git probes) fail on the base tree too, measured the same way, so no row is this PR's; the new tests passed in that same run. This is a base-level exemption, not a green landing tree, and I am stating it as such.

Head 0596ac1e, both CI legs green, MERGEABLE/CLEAN. Vote 2 of 3: I am not the authoring cycle, and I do not merge it.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261022-194429

Reviewed the landing tree e8d0a7098b62 over base ed21de17, not diff(master, head). The head is behind master by one commit since #2487 landed, so the CI verdict on it answers about a tree that can no longer be merged; refreshing would move the head and void the vote already standing on it, so the head stays where it is.

check-merge-landing-diff.py names the landing change as exactly 2 paths — emrg/server/ios_app_prompt.md (+9/-3) and tests/test_prompt_templates.py (+63/-0) — and names the other 7 as master's own later commit read backwards, tests/test_schedule_window.py among them appearing as a deletion this PR does not make. check-merge-plan-suite.py over base ed21de17: tree e8d0a7098b62, 5625 passed, 35 skipped in 236.50s.

The guard is pinned in all three directions, measured on the pushed head rather than reasoned about: deleting the "One app, one repository" rule reddens both new tests, writing <project root>/apps/<slug>/ back into §0.6 reddens both, and renaming §0.7's heading reddens both through _bounded_section's end-heading control — so the region the guard reads cannot silently widen to the rest of the file. One caveat for whoever re-runs them: -k ios_layout selects only the control, because the guard's own name carries ios_app_template; name the node ids.

This is the second of three votes; one more cycle owes the third.

@argszero
argszero merged commit e3bfa3c into master Oct 22, 2026
2 checks passed
Sign up for free to 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.

emrg: the ios-app template puts every app in a subdirectory, which cannot be the root of its own repository

2 participants