Skip to content

GPT Image 2.5 Prompt Archive Implementation Plan ​

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

进度(2026-09-24):Task 1–2 已完成——档案写入脚本、manifest 校验、dry-run 与 --help 均已落地,node --test tests/gpt-image-prompt-archive.test.mjs 6 项测试全部通过(提交 e0f6dde、3d45640)。Task 3–5(页面组件与导航、首次内容归档)待后续实施。

Goal: Build a VitePress visual archive that publishes only final reverse-engineered prompts, their Codex-generated images, and traceable ChatGPT shared-session sources.

Architecture: scripts/gpt-image-prompt-archive.mjs owns stable record IDs, validation, deduplication, and the static JSON update. Codex is the orchestration boundary: when the user asks for an update, it reads the shared session, uses the built-in image generation capability for each new prompt, copies images into docs/public/gpt-image-prompts/, then invokes the script to atomically register completed assets. The Vue component reads the JSON and supplies source filtering, full prompt expansion, and clipboard copy.

Tech Stack: Node.js built-in test runner and crypto/fs modules; VitePress 1.6; Vue 3 Composition API; Codex built-in image generation (no OPENAI_API_KEY).


File structure ​

PathResponsibility
scripts/gpt-image-prompt-archive.mjsValidate prompt-manifest input, calculate source-scoped IDs, skip existing records, and write the static archive JSON.
tests/gpt-image-prompt-archive.test.mjsUnit and CLI-level behavior for record construction, source-scoped deduplication, validation, and dry runs.
docs/public/gpt-image-prompts.jsonPublished archive data; starts empty and is updated only after image files exist.
docs/public/gpt-image-prompts/Generated png images named by stable record ID.
docs/.vitepress/theme/components/GptImagePromptArchive.vueFetch, filter, render, expand, and copy archive records.
docs/gpt-image-prompts/index.mdSEO-aware VitePress entry page.
docs/.vitepress/theme/index.tsGlobally registers the archive component.
docs/.vitepress/config.tsAdds top navigation and the local archive sidebar.
tests/gpt-image-prompts-page.test.mjsStatic page integration contract for registration, navigation, data path, and copy behavior.
package.jsonAdds the safe JSON-registration command.

Task 1: Create the source-scoped archive writer ​

Files:

  • Create: tests/gpt-image-prompt-archive.test.mjs

  • Create: scripts/gpt-image-prompt-archive.mjs

  • Create: docs/public/gpt-image-prompts.json

  • Modify: package.json

  • [x] Step 1: Write failing tests for stable record construction and source-scoped deduplication.

js
test("buildRecord uses a stable source-and-prompt id and published image path", () => {
  const record = buildRecord({
    prompt: "A sunlit paper sculpture of a fox.",
    sourceUrl: "https://chatgpt.com/share/example",
    sourceTitle: "图片逆向提示词-1",
    image: "gpt-image-prompts/abc123.png",
    createdAt: "2026-09-19T00:00:00.000Z",
  });
  assert.match(record.id, /^[a-f0-9]{16}$/);
  assert.equal(record.image, "/gpt-image-prompts/abc123.png");
  assert.equal(record.model, "gpt-image-2.5-sunburst");
  assert.equal(record.size, "1536x1024");
  assert.equal(record.quality, "high");
});

test("mergeRecords skips a matching source-and-prompt id but retains the same prompt from another source", () => {
  const prompt = "A sunlit paper sculpture of a fox.";
  const sourceA = "https://chatgpt.com/share/a";
  const sourceB = "https://chatgpt.com/share/b";
  const existing = [buildRecord({ prompt, sourceUrl: sourceA, sourceTitle: "A", image: "gpt-image-prompts/a.png", createdAt: "2026-09-19T00:00:00.000Z" })];
  const { added, skipped } = mergeRecords(existing, [
    { prompt, sourceUrl: sourceA, sourceTitle: "A", image: "gpt-image-prompts/a.png", createdAt: "2026-09-19T00:00:00.000Z" },
    { prompt, sourceUrl: sourceB, sourceTitle: "B", image: "gpt-image-prompts/b.png", createdAt: "2026-09-19T00:00:00.000Z" },
  ]);
  assert.equal(skipped.length, 1);
  assert.equal(added.length, 1);
  assert.equal(added[0].sourceUrl, sourceB);
});
  • [x] Step 2: Run the focused test and verify it fails because the module does not exist.

Run: node --test tests/gpt-image-prompt-archive.test.mjs

Expected: failure mentioning scripts/gpt-image-prompt-archive.mjs cannot be imported.

  • [x] Step 3: Implement the minimal archive module.
js
export function recordId(sourceUrl, prompt) {
  return createHash("sha256").update(`${sourceUrl.trim()}\n${prompt.trim()}`).digest("hex").slice(0, 16);
}

export function buildRecord(input) {
  const id = recordId(input.sourceUrl, input.prompt);
  return {
    id,
    prompt: input.prompt.trim(),
    sourceUrl: input.sourceUrl.trim(),
    sourceTitle: input.sourceTitle.trim(),
    image: `/${input.image.replace(/^\/+/, "")}`,
    model: "gpt-image-2.5-sunburst",
    size: "1536x1024",
    quality: "high",
    createdAt: input.createdAt,
  };
}

export function mergeRecords(existing, candidates) {
  const existingIds = new Set(existing.map((record) => record.id));
  const added = [];
  const skipped = [];
  for (const candidate of candidates) {
    const record = buildRecord(candidate);
    if (existingIds.has(record.id)) skipped.push(record);
    else {
      existingIds.add(record.id);
      added.push(record);
    }
  }
  return { added, skipped };
}

Use readFile, writeFile, and mkdir from node:fs/promises for an exported updateArchive({ dataFile, candidates, dryRun }) function. Sort records newest-first by createdAt; write { generatedAt, records } with a trailing newline. Create docs/public/gpt-image-prompts.json as {"generatedAt":"","records":[]}\n and add "register-gpt-image-prompts": "node scripts/gpt-image-prompt-archive.mjs" to package.json.

  • [x] Step 4: Run the focused test and verify it passes.

Run: node --test tests/gpt-image-prompt-archive.test.mjs

Expected: both tests pass.

  • [x] Step 5: Commit the data writer.
bash
git add scripts/gpt-image-prompt-archive.mjs tests/gpt-image-prompt-archive.test.mjs docs/public/gpt-image-prompts.json package.json
git commit -m "feat: add GPT image prompt archive writer"

Task 2: Enforce completed-image input and safe dry runs ​

Files:

  • Modify: tests/gpt-image-prompt-archive.test.mjs

  • Modify: scripts/gpt-image-prompt-archive.mjs

  • [x] Step 1: Write failing tests for required metadata, an existing image, and dry-run immutability.

js
test("updateArchive rejects a candidate whose image does not exist", async () => {
  await assert.rejects(
    updateArchive({ dataFile, imageRoot, candidates: [{ prompt: "Prompt", sourceUrl: "https://chatgpt.com/share/a", sourceTitle: "A", image: "gpt-image-prompts/missing.png", createdAt }], dryRun: false }),
    /生成图片不存在/,
  );
});

test("updateArchive reports a dry run without writing the JSON file", async () => {
  const before = await readFile(dataFile, "utf8");
  const summary = await updateArchive({ dataFile, imageRoot, candidates: [readyCandidate], dryRun: true });
  assert.equal(summary.added, 1);
  assert.equal(await readFile(dataFile, "utf8"), before);
});
  • [x] Step 2: Run the focused test and verify it fails for the new behavior.

Run: node --test tests/gpt-image-prompt-archive.test.mjs

Expected: failing assertions for missing-image acceptance and dry-run writing.

  • [x] Step 3: Implement validation and manifest-based CLI input.

Add validateCandidate(candidate, imageRoot) that rejects blank prompt, invalid https://chatgpt.com/share/ source URLs, blank sourceTitle, invalid image paths, and files absent beneath docs/public. Add --manifest <absolute-or-relative-json-file> and --dry-run; the manifest shape is { "records": [{ "prompt", "sourceUrl", "sourceTitle", "image", "createdAt" }] }. Print exactly added=<n> skipped=<n> dryRun=<true|false> on success, and let thrown validation errors terminate with a nonzero status.

  • [x] Step 4: Run focused tests and the CLI dry run.

Run: node --test tests/gpt-image-prompt-archive.test.mjs && npm run register-gpt-image-prompts -- --help

Expected: tests pass and help documents --manifest and --dry-run without modifying archive JSON.

  • [x] Step 5: Commit the safe registration boundary.
bash
git add scripts/gpt-image-prompt-archive.mjs tests/gpt-image-prompt-archive.test.mjs
git commit -m "feat: validate GPT image archive manifests"

Task 3: Add the visual archive component and page contract ​

Files:

  • Create: tests/gpt-image-prompts-page.test.mjs

  • Create: docs/.vitepress/theme/components/GptImagePromptArchive.vue

  • Create: docs/gpt-image-prompts/index.md

  • Modify: docs/.vitepress/theme/index.ts

  • [ ] Step 1: Write the failing static integration test.

js
test("GPT image prompt archive has a registered page and data-backed component", () => {
  assert.equal(existsSync(pagePath), true);
  assert.equal(existsSync(componentPath), true);
  assert.match(readFileSync(pagePath, "utf8"), /<GptImagePromptArchive \/>/);
  assert.match(readFileSync(themeIndex, "utf8"), /app\.component\("GptImagePromptArchive", GptImagePromptArchive\)/);
  const component = readFileSync(componentPath, "utf8");
  assert.match(component, /fetch\(withBase\("\/gpt-image-prompts\.json"\)\)/);
  assert.match(component, /navigator\.clipboard.*writeText/);
  assert.match(component, /sourceUrl/);
});
  • [ ] Step 2: Run the focused test and verify it fails because the archive files are absent.

Run: node --test tests/gpt-image-prompts-page.test.mjs

Expected: failure that docs/gpt-image-prompts/index.md does not exist.

  • [ ] Step 3: Implement the page and focused Vue component.

Create the page with:

md
---
layout: doc
title: GPT Image 2.5 提示词档案
description: 收录逆向生成后的最终提示词,并以 GPT Image 2.5 生成配图;每条记录可追溯到原始会话。
aside: false
pageClass: gpt-image-prompts-page
---

# GPT Image 2.5 提示词档案

<GptImagePromptArchive />

In the component, declare ArchiveRecord and ArchiveData types matching Task 1. Fetch withBase("/gpt-image-prompts.json") in onMounted, derive distinct sources, filter with an activeSource ref, show an image card per record, and use a <details> block for the exact prompt plus a 复制提示词 button. Copy errors must set visible, nonfatal status text. External source links require target="_blank" rel="noopener". Keep all component styles scoped, responsive, and consistent with existing VitePress variables.

Register GptImagePromptArchive in theme/index.ts in the same enhanceApp block as GithubProjects.

  • [ ] Step 4: Run the focused page contract test.

Run: node --test tests/gpt-image-prompts-page.test.mjs

Expected: pass.

  • [ ] Step 5: Commit the reader experience.
bash
git add docs/.vitepress/theme/components/GptImagePromptArchive.vue docs/gpt-image-prompts/index.md docs/.vitepress/theme/index.ts tests/gpt-image-prompts-page.test.mjs
git commit -m "feat: add GPT image prompt archive page"

Task 4: Wire discovery navigation and build verification ​

Files:

  • Modify: tests/gpt-image-prompts-page.test.mjs

  • Modify: docs/.vitepress/config.ts

  • Modify: docs/.vitepress/theme/style.css

  • [ ] Step 1: Extend the failing contract test for discoverability.

js
test("GPT image prompt archive is reachable from navigation and its own sidebar", () => {
  const config = readFileSync(path.join(root, "docs", ".vitepress", "config.ts"), "utf8");
  assert.match(config, /text: "GPT Image 2\.5", link: "\/gpt-image-prompts\/"/);
  assert.match(config, /"\/gpt-image-prompts\/"/);
  assert.match(config, /text: "提示词图鉴", link: "\/gpt-image-prompts\/"/);
});
  • [ ] Step 2: Run the focused test and verify it fails on missing navigation.

Run: node --test tests/gpt-image-prompts-page.test.mjs

Expected: failure matching the absent navigation text.

  • [ ] Step 3: Add navigation, sidebar, and motion parity.

Add { text: "GPT Image 2.5", link: "/gpt-image-prompts/" } to the primary nav array. Add a "/gpt-image-prompts/" sidebar section titled GPT Image 2.5 提示词档案 whose sole item is 提示词图鉴. Add .vp-doc .GptImagePromptArchive to both the normal and reduced-motion selector groups in style.css, so the new component follows the existing entry-motion accessibility policy.

  • [ ] Step 4: Run focused test and full static-site build.

Run: node --test tests/gpt-image-prompt-archive.test.mjs tests/gpt-image-prompts-page.test.mjs && npm run build

Expected: every listed test passes and VitePress exits with status 0.

  • [ ] Step 5: Commit site integration.
bash
git add docs/.vitepress/config.ts docs/.vitepress/theme/style.css tests/gpt-image-prompts-page.test.mjs
git commit -m "feat: expose GPT image prompt archive"

Task 5: Perform the first agent-mediated archive update ​

Files:

  • Create: docs/public/gpt-image-prompts/<record-id>.png (one file per successfully generated prompt)

  • Modify: docs/public/gpt-image-prompts.json

  • Create: tmp/gpt-image-prompts-initial-manifest.json (temporary; delete before commit)

  • [ ] Step 1: Read the current source session and extract only final prompts.

Open https://chatgpt.com/share/6aaea0e7-faf4-83ea-8342-c4b131ac1713 in Codex browser tooling. Extract only the final reverse-engineered prompts; exclude reference images, analysis, conversational filler, and duplicates. If the public page does not return visible conversation text, stop this task without altering the archive and ask the user to reopen/re-share it or provide an exported text transcript.

  • [ ] Step 2: Generate each new candidate with Codex’s built-in image generator.

For each extracted final prompt, invoke the built-in image generator once using the prompt verbatim. Request 1536x1024 at high quality. Inspect each result for a nonempty image asset, then copy the selected image into docs/public/gpt-image-prompts/<record-id>.png; do not overwrite an existing file.

  • [ ] Step 3: Write and dry-run the temporary manifest.
json
{
  "records": [
    {
      "prompt": "<verbatim extracted final prompt>",
      "sourceUrl": "https://chatgpt.com/share/6aaea0e7-faf4-83ea-8342-c4b131ac1713",
      "sourceTitle": "图片逆向提示词-1",
      "image": "gpt-image-prompts/<record-id>.png",
      "createdAt": "2026-09-19T00:00:00.000Z"
    }
  ]
}

Run: npm run register-gpt-image-prompts -- --manifest tmp/gpt-image-prompts-initial-manifest.json --dry-run

Expected: output reports the number of newly added and skipped records; docs/public/gpt-image-prompts.json is unchanged.

  • [ ] Step 4: Register assets and verify record-to-image correspondence.

Run: npm run register-gpt-image-prompts -- --manifest tmp/gpt-image-prompts-initial-manifest.json && node --input-type=module -e 'import fs from "node:fs"; const data=JSON.parse(fs.readFileSync("docs/public/gpt-image-prompts.json","utf8")); for (const record of data.records) { if (!fs.existsSync(docs/public${record.image})) throw new Error(missing ${record.image}); } console.log(${data.records.length} records have images)'

Expected: writer succeeds and every published record resolves to a local image. Delete the temporary manifest after this verification.

  • [ ] Step 5: Build, inspect, and commit the initial data.

Run: npm run build && git status --short

Expected: build exits with status 0; staged changes contain only the intended image assets and archive JSON, never tmp/, .superpowers/, credentials, or unrelated promo-video/ files.

bash
git add docs/public/gpt-image-prompts.json docs/public/gpt-image-prompts
git commit -m "content: add initial GPT image prompt archive"

Plan self-review ​

  • Spec coverage: Tasks 1–2 implement source-scoped IDs, no-key operation boundary, completed-image-only registration, failures, and dry runs. Tasks 3–4 implement the filterable visual catalog, full prompt view/copy, source links, navigation, sidebar, and build coverage. Task 5 defines the Codex-only extraction/generation workflow and preserves the no-reference-image boundary.
  • Placeholder scan: No implementation task depends on undefined code names. The placeholder-looking fields in Task 5 are a manifest template deliberately replaced with the actual extracted prompt and stable ID only after the source is available; they are not production code or an unimplemented requirement.
  • Type consistency: ArchiveRecord, buildRecord, mergeRecords, updateArchive, sourceUrl, sourceTitle, image, model, size, quality, and createdAt use the same spellings throughout.

Last updated:

最后更新2026-09-23
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题