Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e54952a
Merge issue/57 into epic/E3-icon-pipeline
CompleteDotTech Oct 30, 2026
8ed5350
docs: write the Codex image-generation recipe (E3.4.1, #65)
CompleteDotTech Oct 30, 2026
db902d4
docs: address E3 review on the Codex recipe (E3.4.1, #65)
CompleteDotTech Oct 30, 2026
ca48d48
test: harden the Codex recipe guards (E3.4.1, #65)
CompleteDotTech Oct 30, 2026
2c5a820
Merge task/64-65
CompleteDotTech Oct 30, 2026
5c2cd57
docs: add privacy and sandbox notes to the Codex recipe (E3.4.2, #66)
CompleteDotTech Oct 30, 2026
ef91bb7
Merge task/64-66
CompleteDotTech Oct 30, 2026
6c0baf0
docs: state icon prompt generator does not filter private facts
CompleteDotTech Oct 30, 2026
f1880bc
docs: record relative provenance path and apply Codex attempt cap per…
CompleteDotTech Oct 30, 2026
ea77a79
Fix E741 ambiguous variable name in art-direction recipe test
CompleteDotTech Oct 30, 2026
34afee6
Merge origin/main into issue/64
CompleteDotTech Nov 1, 2026
1e0bdee
test: pin recipe base table rows to merged main art-direction brand rows
CompleteDotTech Nov 1, 2026
1597e69
test: add static wording guards for #64 recipe observed-runtime and c…
CompleteDotTech Nov 1, 2026
d0b7a99
docs: align Codex recipe with candidate contract and observed notes
CompleteDotTech Nov 1, 2026
30a60fa
Merge Haiku art-direction docs (d0b7a99)
CompleteDotTech Nov 1, 2026
ac822c0
Merge Haiku recipe tests (1597e69)
CompleteDotTech Nov 1, 2026
2bb3e3a
docs: state observed-runtime labelling and per-slot candidate contrac…
CompleteDotTech Nov 1, 2026
2ff0a49
test: guard unreadable-only candidate runs against the slot budget (#64)
Nov 1, 2026
f17925d
docs: treat unreadable image paths as empty runs in the Codex recipe
CompleteDotTech Nov 1, 2026
0a335da
Merge Haiku art-direction docs (f17925d)
CompleteDotTech Nov 1, 2026
9ace6cc
Merge Haiku recipe tests (2ff0a49)
CompleteDotTech Nov 1, 2026
e4cdb39
docs: note unreadable-only output counts as an empty attempt in #64 c…
CompleteDotTech Nov 1, 2026
8a61eff
docs: apply four accepted Opus P3 fixes to Codex image recipe (#64)
CompleteDotTech Nov 1, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ All notable changes to `github-showcase-skill` are recorded here. Versions follo
- `content icon check` and `content icon normalize` take `--min-contrast` (and the family key `icon_min_contrast`, range 1 to 21) to set the contrast floor of the icon ink on the card. Precedence is the flag, then the family key, then the default 3.0, so existing results do not change. 4.5:1 is recommended for the card plate but is not the default.
- `content icon check` and `content icon normalize` take `--strict` (and the family key `icon_strict_family_ink: true`, off by default) to fail instead of warn when the dominant icon ink is not a family ink. Without a family palette the family-ink check is still not emitted.
- `org labels ORG --repos-from-gh` plans labels across accessible repositories without the private estate registry, with paginated read-only GitHub capture, optional verified local checkouts, unchanged reference guards, and a documented org-default-forms-first workflow. Registry-backed plans still require the org registry row, and checkout repository names match GitHub case-insensitively, including resolved pending renames. Registry-free runs also isolate lazy brand lookups from estate decision files, and held reference rewrites retain their file/line guidance with an incomplete result. Workflow/labeler/release/Renovate references remain final skips rather than unresolved input requests. Missing Windows device-named checkouts fall back to captured metadata instead of aborting the org plan. Pending transfers check the repository's current owner's default issue forms and hold renames when that evidence is unavailable. Sparse or partially missing checkouts retain reference holds based on captured paths and the Git index, while unrelated omitted files remain allowed.
- `references/art-direction.md` documents the Codex image-generation recipe for the icon pipeline (the `codex exec` command, reading the image path from the run output, and the retry and attempt limits). Image-folder and sandbox notes are labelled as observed runtime behaviour, not OpenAI-documented, and the exact returned path is the rule. Each distinct returned path is one candidate, and the attempt cap is per candidate slot (four slots, 3 empty attempts each); unreadable-only output counts as an empty attempt and ends in `art-fail` after 3. Documentation and static wording tests only; no behaviour change.

### Fixed

Expand Down
54 changes: 54 additions & 0 deletions references/art-direction.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,60 @@ Starred values are approximate until the estate planner re-measures them and pub
| Screenshot (B, E) | `assets/screenshot.webp` | 1600×1000 viewport | WebP q80 ≤ 300 KB; captured from the live URL in a browser, never drawn by an image model |
| Provenance | `assets/PROMPTS.md`, `.github/profile/assets/PROMPTS.md` | — | Markdown, one block per committed generated asset |

## Codex image-generation recipe

### Command

The prompt comes from `content icon prompt` (written with `--out`, for example `art/prompts/ORG/REPO/icon.md`); give it to Codex non-interactively:

```bash
codex exec --skip-git-repo-check --json "$(cat art/prompts/ORG/REPO/icon.md)" > run.jsonl
```

- `exec` runs one non-interactive turn.
- `--skip-git-repo-check` lets it run from a scratch directory.
- `--json` prints one JSON event per line, so the run output can be parsed (the image path is read from it, see below).
- `--sandbox MODE` selects the sandbox policy for model-generated shell commands.
- `--output-last-message FILE` also writes the final message to FILE.
- A prompt of `-` is read from standard input.

Use the same model and version for a whole family run (pipeline rule 4). Record the tool, model id and version in `PROMPTS.md` exactly as the run reports them; if the run does not expose a model id, write `not exposed` in the `TOOL / MODEL ID AND VERSION` field. Never invent a model id. Flag names follow codex-cli 0.166.0 at the time of writing; if one is rejected, run `codex exec --help` and change nothing else in the recipe.

This recipe does not rely on a documented image path: OpenAI documentation covers non-interactive `codex exec` and its JSON events, not where generated images are stored, so always use the exact path returned by the run output.

### Read the image path from the run output

1. After the run, search the `run.jsonl` events (or the final message) for every image file path Codex reports for the generated images, and use exactly those paths (see item 5).
2. Never pick the newest file in the generated-images folder. Parallel sessions write into the same place, so the newest file can belong to another run and the wrong image gets normalized.
3. If the run output names no readable image path, treat the attempt as an empty run (see Retry and attempt limits). Do not fall back to the newest file or to a directory listing.
4. Copy the chosen image to scratch (see Sandbox (d)) and pass that copy to content icon normalize --in PATH, not the generated_images path. In the `PROMPTS.md` provenance block, record the Codex session id and only the image file name, or the path written relative to `$CODEX_HOME` (for example `$CODEX_HOME/generated_images/<file>`), in the prose beside the record. Never record the absolute path: it contains the local user name. The Provenance record fenced template itself does not change.
5. One invocation may report between zero and four image paths. Every DISTINCT path the run output reports is one candidate; use exactly the reported paths, never a directory listing or the newest file. A run that reports no readable path is an empty run: either it reports no path, or every path it reports is unreadable (unreadable-only output). An unreadable path fills no slot, and readable paths in the same run still fill their slots. Parallel sessions write into the same place, so do not run candidates for several repositories in the same working directory at once unless you can tell their outputs apart.

### Retry and attempt limits

- The limit applies per candidate, not per candidate set. Pipeline rule 7 asks for four candidates (the option A template also says so), so there are four candidate slots, and the cap applies to each slot. A run that returns k distinct readable paths fills k slots (up to the unfilled ones); make further runs, with the same unchanged prompt, only for unfilled slots.
- An empty run (no path, or unreadable-only output) is retried as a NEW run with the same unchanged prompt, at most 2 retries (3 attempts total) for each slot that is still unfilled. Each empty run counts as one attempt against every slot that is still unfilled. Parallel runs can finish without a path, which is why a retry is allowed. Retries never alter the prompt.
- Successful candidates never count toward the cap, so the four-candidate round of pipeline rule 7 (then 4 more once, then log `art-fail`) is still reachable. Only empty runs count toward the 3 attempts, and they are not candidates. An unreadable path is not a successful candidate, so unreadable-only output is counted as an empty run and cannot loop forever.
- The second round of rule 7 ("4 more once") opens four new slots with the same per-slot cap of 3 attempts (2 retries each); slots from the first round do not carry over their attempt counts.
- After 3 empty attempts for any one slot, including attempts that returned only unreadable paths, stop and log `art-fail` with a one-line reason. Do not loop.

### Privacy: only public facts go into prompts

- (a) Prompts may contain only public facts: the public repository name, its public description and topics, the family palette and style lock, and the glyph fields supplied by the writer.
- (b) Never paste private-repository content into a prompt: no private repo names, README or source text, issue text, customer or personal data, emails, tokens, or estate-registry rows.
- (c) `content icon prompt` does not establish whether a fact is public. It writes repository metadata (name, description, topics) and fields derived from the local README, such as its heading, into the Markdown file that Codex receives, with no privacy filtering. Before running Codex, read the complete generated Markdown, including every README-derived field, and remove or replace anything that is not public. Use public-only inputs, or hold the task. The prompt leaves the machine.
- (d) For a private repository, do not generate the icon with Codex from its contents. Use only the family glyph fields and a neutral name, or hold the task.
- (e) Keep the prompt text in the provenance record verbatim, which makes this rule auditable.

### Sandbox: read from the generated-images folder

These are OBSERVED runtime notes from issue #64 and the Pick Your AI evidence, not behaviour documented by OpenAI. Do not cite OpenAI documentation for them; the rule that holds regardless is: use the exact path returned by the run output.

- (a) Observed: Codex stored generated images in its `generated_images` folder inside `$CODEX_HOME` (default: the `.codex` folder in the user's home, `~`). Read the image from the path named in the run output, which points there.
- (b) Observed: files that Codex writes into its own sandbox, for example a copy it saves into the working directory it was given, can be locked against the user account (access denied). Do not rely on them, and do not try to chmod or take ownership of them.
- (c) If a path is unreadable, copy nothing from the sandbox and do not retry the same path. Treat that path as returning nothing: if the same run reports another readable path in the generated-images folder, use that; otherwise the run is an empty run and counts as one attempt under the retry limit above, ending in `art-fail` after 3 empty attempts for the slot.
- (d) Copy the chosen image to a scratch location outside the repository before `content icon normalize --in`, and commit only the normalized `assets/icon.png`. Never commit the raw candidate. Do not write any real absolute local path or user name; use `$CODEX_HOME` and `~` only.

## Repository glyph prompt template

`content icon prompt` uses this self-contained option A template by default. Its
Expand Down
2 changes: 1 addition & 1 deletion references/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ both tokens and exits 4 with their names; add them to the custom config or pass
tokens for every family. Option B uses the illustration palette and does not
require these glyph tokens, whether art direction is selected implicitly or explicitly.

All actions run on a checkout and a metadata file alone. The registry and approvals refine the result when present (a renamed org's packages and links resolve to its current login; a registry `language:` override reaches the chip); without them the resolver uses `references/brand.yaml` and treats nothing as approved. `icon prompt`, `icon normalize` and `icon check` default to the skill's bundled [art-direction.md](art-direction.md), regardless of the working directory. Option A uses its repository glyph template and the family's `brand.yaml` tokens; option B uses its illustration template. Pass `--art-direction FILE` to select an explicit art direction file (relative paths resolve from the current directory), including an estate-format file with `(b) Family palette` and `(d) Shared prompt template` sections. A missing selected file reports `needs-input:art-direction` and names that path; `prompt` exits 4, while normalization and QA log the missing palette and continue their other checks.
All actions run on a checkout and a metadata file alone. The registry and approvals refine the result when present (a renamed org's packages and links resolve to its current login; a registry `language:` override reaches the chip); without them the resolver uses `references/brand.yaml` and treats nothing as approved. `icon prompt`, `icon normalize` and `icon check` default to the skill's bundled [art-direction.md](art-direction.md), regardless of the working directory. Option A uses its repository glyph template and the family's `brand.yaml` tokens; option B uses its illustration template. Pass `--art-direction FILE` to select an explicit art direction file (relative paths resolve from the current directory), including an estate-format file with `(b) Family palette` and `(d) Shared prompt template` sections. A missing selected file reports `needs-input:art-direction` and names that path; `prompt` exits 4, while normalization and QA log the missing palette and continue their other checks. The Codex recipe for producing the candidate image (command, how to read its path, retry limit) is in [art-direction.md](art-direction.md#codex-image-generation-recipe).
Loading
Loading