Skip to content

TASK-562 - Export a selection of components as a plan and import it as drafts - #120

Open
MrLesk wants to merge 6 commits into
mainfrom
task-562-plans
Open

MrLesk wants to merge 6 commits into
mainfrom
task-562-plans

Conversation

@MrLesk

@MrLesk MrLesk commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Implements TASK-562. groma plan export <ids...> --to <directory> writes a plan: an OKF bundle with the selected elements as drafts, the relationships between them as draft rows, and the flows that lie entirely inside the selection. Parents outside the selection are named by id only. groma plan import <directory> [--parent <id>] brings the plan into another repository as ghosts under one draft record named after the plan. A colliding id or a missing parent fails the whole import before anything is written.

On the live web map, a multi-selection of components offers Export as plan next to Group as and Combine into. groma plan on its own explains what a plan is, and docs/plans.md walks through an example. The component Markdown contract describes the bundle.

A Codex agent (GPT-6.1 Sol) built this live during the Devoxx Belgium keynote on 9 October, working TASK-562 in one checkout it shared with five other agents. This branch holds only this task's changes: I matched every changed line to the agent session that wrote it and rebuilt the task on a fresh branch from main.

Acceptance criteria, as the agent left them

  • groma plan export <ids...> --to writes a plan bundle in the OKF profile: the selected elements with status draft and their overviews, the relationships between them as draft rows, the flows that lie entirely within the selection, and the parents they need by id only. The Markdown contract documents the bundle.
  • groma plan import [--parent ] creates the elements as ghosts at the paths they will keep, the relationships as draft rows, and a draft record named after the plan that tags every imported element. Ids are kept. A colliding id or a missing parent fails the whole import with a message naming it, and nothing is written.
  • On the web map, a multi-selection of components offers Export as plan beside Group as and Combine into, and the bundle is written into the repository or downloaded.
  • After an import, a scan matches the ghosts when their code arrives and groma accept works unchanged. Existing draft behaviour and its tests stay as they are.
  • A round trip works: a plan exported from one fixture repository and imported into an empty one yields equal elements, relationships and overviews.
  • groma plan without arguments prints what a plan is and the two commands, and docs/ gets a page with an example plan.

The agent left the browser export unticked: it verified the CLI round trip on a fixture, but not the button in a browser.

Validation

On stage the agents were told not to install, build or run tests, so these are the first runs of this code.

  • bun run typecheck passes.
  • biome lint: no errors, no new warnings.
  • Node tests: 16 pass. Bun suite: 776 pass, 51 skip, 0 fail, the same as main.
  • The agent's own CLI walkthrough: a round trip kept 6 element meanings, 4 relationships and 1 flow equal, a re-import failed without touching any file, and imported ghosts scanned and accepted.

Overlap with the other PRs from this run

map-session.ts, data.ts, write-commands.ts, organisms/writes.ts and the component Markdown contract are shared with other PRs from the same run. Each adds separate lines or sections.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T19:27:59.667637Z 2e07df3 New commits
🔒 Security Review ✅ Completed 2026-10-09T09:20:54.452772Z 1146eeb PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Groma architecture comparison

Changes Added Modified Removed
Components 1 10 0
Relationships 0 0 0

Open before / after comparison

Compared 4b19ce0 (merge base) → 2e07df3.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1146eeb875

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/plan.ts Outdated
Comment thread src/relationship-markdown.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e07df3ded

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/plan.ts
const filenames = new Map(selected.map(element => [element.id, element.sourceFilename]))
const rows = selectedRelationships(model, ids)
const files = new Map<string, string>()
files.set('plan.md', sourceWithFrontmatter({ type: PLAN_TYPE, title: path.basename(to) }, '\n\nArchitecture to implement.\n'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject plan names that collide with bundled IDs

When the output directory's basename normalizes to one of the selected IDs—for example, groma plan export checkout --to ../checkout—this writes a bundle that cannot be imported even into an empty project: requireFreeIds derives the draft ID checkout from this title and then rejects it because the bundle already contains that element ID. Validate the title-derived draft ID during export so a successful export is not inherently unusable.

AGENTS.md reference: AGENTS.md:L265-L267

Useful? React with 👍 / 👎.

Comment thread src/plan.ts
Comment on lines +86 to +87
id: flow.id, title: flow.title, description: flow.description, overview: escapeMarkdownText(flow.overview),
steps: `| From | To | Action |\n| --- | --- | --- |\n${rows.join('\n')}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve literal block markers in flow overviews

When a valid flow overview contains literal block-leading text—for example, Markdown source \# Not a heading—resolveFlows decodes it to # Not a heading, but this call escapes only inline syntax before re-emitting it. The exported plan therefore contains an actual level-one heading and import rejects it, while escaped list or blockquote markers silently change the overview structure. Preserve the overview Markdown or also escape block syntax at line starts so exporting a valid flow cannot produce an invalid or semantically changed bundle.

AGENTS.md reference: AGENTS.md:L265-L267

Useful? React with 👍 / 👎.

Comment thread src/plan.ts
Comment on lines +109 to +110
if (isInside(filesystem.absolute(), to)) {
throw new Error(`"${input.to}" is inside ${filesystem.directory}/, where a plan would be read as architecture`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refuse export into the alternate Groma root

When a repository currently uses groma/, exporting to .groma or a child such as .groma/plans/x passes this check because it only compares against the active root; the reverse occurs when .groma/ is active. The successful export creates the alternate recognized architecture directory, after which every command fails with Both groma/ and .groma/ exist. Reject destinations inside either reserved root when that path is within the repository.

AGENTS.md reference: AGENTS.md:L265-L267

Useful? React with 👍 / 👎.

@MrLesk MrLesk changed the title Export a selection of components as a plan and import it as drafts TASK-562 - Export a selection of components as a plan and import it as drafts Oct 13, 2026

This branch was successfully deployed

1 active deployment
github-pages — 2e07df3d Deployed Oct 11, 2026 by MrLesk via deploy #207
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.

1 participant