Skip to content

feat(plugins): generate Codex workflows as skills (#162) - #164

Open
isolomatov-gd wants to merge 9 commits into
mainfrom
feat/codex-workflows-as-skills
Open

feat(plugins): generate Codex workflows as skills (#162)#164
isolomatov-gd wants to merge 9 commits into
mainfrom
feat/codex-workflows-as-skills

Conversation

@isolomatov-gd

@isolomatov-gd isolomatov-gd commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Closes #162.

Codex emitted workflows as flat documents under .agents/workflows/ plus a workflows index, so they never surfaced as invokable skills.

Change

The Antigravity workflow-to-skill transform is generalized and composed in both targets. SpecEntry.target owns placement: fileWorkflowToSkill derives its base from the incoming frame.target rather than a hardcoded root, so one no-argument processor serves Codex (.agents/skills) and Antigravity (skills).

PluginSpec unchanged; no factory, flag, branch, or move stage. Bootstrap code untouched — the Codex workflows-index payload entry drops out through existing absent-document handling.

Before After
Codex workflows .agents/workflows/*.md + INDEX.md .agents/skills/<name>/SKILL.md + phases/
Codex session hook injects "Rosetta Workflows Index" no workflows index
Antigravity unchanged layout phases now body-only
Other 5 targets byte-identical

Also in scope:

  • pluginReplaceLiterals(pairs) (FR-ARCH-0058) — exact literal substitution, composed via buildPipeline's extraAfterIndexes into Codex and Antigravity only. Corrects plugin-files-mode.md's WORKFLOW/COMMAND `workflows/*.md` to the skills form. Plain substring matching, no boundary/regex guards: the target is prose, not a path token. Runs before the bootstrap assembler, so hook payloads inherit it.
  • Folder-level rewrite restricted to pure relocations (FR-ARCH-0049) — a workflows/skills/ token pair is only meaningful when a document keeps its identity as one path segment. Discriminated by depth, so extension-only renames (.md.mdc) still qualify.
  • Bootstrap prefix removedBOOTSTRAP_PREFIX and the isLead field are gone; hooks are small and get_context_instructions is unused in this flow. Leading-newline stripping now applies to every entry.
  • Phase files no longer open with a blank line.
  • Codex manifestRosetta 3, $-prefixed example prompts, and no reference to the removed workflows index.
  • r2 plugin-files-mode.md bullets normalized so both releases carry one identical literal.

Requirements

FR-HOOK-0007's r3 session-start entry counts were wrong for every target: r3 consolidates five split bootstrap-* rules into one bootstrap-alwayson.md. Corrected to Claude/Copilot r2=9 / r3=5, Codex r2=8 / r3=4, now asserted against the real instruction tree.

FR-HOOK-0003 Deprecated. FR-HOOK-0009 restated — manifest order governs payload sequence only, no lead designation. GLOSSARY, ASSUMPTIONS QF-1, NFR-0004 reconciled.

Set to Implemented: FR-COPY-0080, FR-VAR-0041, FR-VAR-0042, FR-HOOK-0007, FR-HOOK-0009, FR-STRUCT-0010, FR-STRUCT-0030, FR-ARCH-0049, FR-ARCH-0058.

Plugin manifest fix

core-antigravity's plugin manifest was a patch behind the other four at 3.1.0. scripts/bump_versions.sh never listed it — its manifest sits at the plugin root rather than under a *-plugin/ config folder. Bumped to 3.1.1 and added to the script so it cannot be skipped again.

Verification

Build and typecheck clean. rosettify-plugins 49 files / 572 tests; hooks 33 files / 1142 tests.

Checked against real r2 and r3 output for all seven targets: skill and phase placement, stripped phase frontmatter, no workflows/INDEX or "Rosetta Workflows Index" anywhere in the Codex tree, all six hook counts re-derived from raw JSON with the plugin-root entry last, cross-references still rewriting, cursor/copilot relocation intact, other five targets byte-identical.

parity-derive-structure.ts derives expected paths independently of production code. Test fixtures are additive.

plugins/ is regenerated output — --release r3 --deterministic-hooks false, no hand edits.

🤖 Generated with Claude Code

Codex workflows were emitted as flat documents under `.agents/workflows/`
plus a workflows index, so they never surfaced as invokable skills.

Generalize the existing Antigravity workflow-to-skill transform and compose
it in both targets. `SpecEntry.target` becomes the sole owner of placement:
`fileWorkflowToSkill` derives its base from the incoming `frame.target` set
by `computeTargetPath` rather than hardcoding a target root, so the same
no-argument processor serves Codex (`.agents/skills`) and Antigravity
(`skills`). `PluginSpec` is unchanged and no factory, flag, or move stage is
introduced.

Codex now emits `.agents/skills/<workflow>/SKILL.md` with owned phases under
`phases/`, frontmatter stripped. Its workflows-index declaration is removed;
the payload entry disappears through existing absent-document handling, with
bootstrap code untouched.

Two defects found during review and fixed:

- `buildRenamePairs` emitted a blanket `workflows/` -> `skills/` folder token
  pair. That is only valid for a pure folder relocation such as Cursor's
  `workflows/` -> `commands/`, where a document keeps its identity as one
  path segment. Under a restructuring mapping a bare folder token has no
  document identity, so the rewrite produced nonexistent paths and corrupted
  prose: the shipped Antigravity bootstrap lead document read
  `WORKFLOW/COMMAND `skills/*.md``, contradicting its own
  `SKILL `skills/*/SKILL.md`` entry. Folder pairs are now emitted only for
  pure relocations, discriminated by depth rather than basename equality, so
  extension-only renames still qualify. FR-ARCH-0049 mandated the unqualified
  behavior and was corrected first.
- `.codex-plugin/plugin.json` told the agent to consult `workflows/INDEX.md`,
  a file this change removes. Preserved configs are byte-copied and never
  pass through `pluginRewriteReferences`, so the dangling pointer would have
  shipped silently.

FR-HOOK-0007's r3 session-start entry counts were overstated by three for
every target: r3 consolidates the five split `bootstrap-*` rules into one
`bootstrap-alwayson.md` and the absent basenames are skipped. Corrected to
Claude/Copilot r2=9 r3=5 and Codex r2=8 r3=4, and now asserted against the
real instruction tree.

Requirements: FR-COPY-0080, FR-VAR-0041, FR-VAR-0042, FR-HOOK-0007,
FR-STRUCT-0010, FR-STRUCT-0030, FR-ARCH-0049 — all set to Implemented with
file and test evidence.

Verified on real r2 and r3 output for all seven targets: the other five
regenerate byte-identical; Antigravity's only diffs are phase-frontmatter
removal and the prose corrections. Suite at 48 files / 535 tests.

Generated `plugins/` tree and manifest versions are intentionally left
un-regenerated; only `src/rosettify-plugins/package.json` is bumped to 3.2.0.

Closes #162

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added enhancement New feature or request bug Something isn't working labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Rosetta Triage Review

Summary: This PR generalizes the Antigravity fileWorkflowToSkill transform to also serve Codex, fixing issue #162 where Codex workflows were emitted as flat documents under .agents/workflows/ instead of surfacing as invokable skills. It also corrects two defects found during review: a blanket folder-token rewrite that corrupted the shipped Antigravity bootstrap lead document, and a stale manifest pointer in plugins/core-codex/.codex-plugin/plugin.json.

Findings:

  • Code quality — solid. fileWorkflowToSkill correctly derives targetBase from the incoming frame.target (set by SpecEntry.target) rather than hardcoding a root, making the processor truly target-agnostic and composable. The isPureFolderRelocation discriminant in buildRenamePairs is the right fix for the blanket-token corruption bug — it gates folder-pair emission on depth/structure, not basename equality.
  • Test coverage — comprehensive. New file-workflow-to-skill.test.ts (344 lines) covers both skills and .agents/skills bases via describe.each, replacing the prior Antigravity-only test (203 lines). New targets-codex-output.test.ts (224 lines) runs the full coreCodex pipeline E2E against a temp instruction tree. New bootstrap-session-start.e2e.test.ts (206 lines) asserts session-start counts from the real instruction tree (preventing the count-overstated regression that FR-HOOK-0007 had). Suite grows to 535 tests.
  • Requirements traceability — complete. Seven FRs corrected or added (FR-COPY-0080, FR-VAR-0041/0042, FR-HOOK-0007, FR-STRUCT-0010/0030, FR-ARCH-0049), all set to Implemented with file and test evidence. The addition of a criterion to FR-VAR-0041 guarding against stale manifest pointers is a good preventive measure.
  • Scope — well-focused. The change is narrowly contained to the plugin generator (src/rosettify-plugins/), requirements docs, and plans. The other five plugin targets are byte-identical per verification.
  • Breaking change — intentional and documented. Codex plugin tree layout changes from .agents/workflows/ to .agents/skills/; this is the fix for Codex: workflow is not visible #162. The Antigravity bootstrap corruption fix changes prior (broken) behavior.
  • Regeneration gap — process risk. The PR intentionally leaves the committed plugins/ tree un-regenerated (plugins/core-codex/.codex-plugin/plugin.json still carries the old pointer and version 3.1.0 until maintainer regenerates). This is documented in the PR notes but should be tracked as a required follow-up step at release time to avoid shipping a stale manifest.

Suggestions:

  • Consider a brief note in CONTRIBUTING.md or DEVELOPER_GUIDE.md (or a TODO comment in the workflow) reminding maintainers that scripts/pre_commit.py must be run after merging any change to src/rosettify-plugins/ before tagging a release — the current state (package bumped to 3.2.0, plugins still at 3.1.0) is intentional now but easy to miss under time pressure.

Automated triage by Rosetta agent

isolomatov-gd and others added 7 commits July 28, 2026 19:53
Signed-off-by: isolomatov-gd <isolomatov@griddynamics.com>
…ated plugins

Follow-up to the workflows-as-skills change, from inspecting real generated
output.

Glob documentation pointed at a layout that no longer exists. For Codex and
Antigravity, `rules/plugin-files-mode.md` still read
`WORKFLOW/COMMAND `workflows/*.md`` even though those targets restructure
workflows into skills. `pluginRewriteReferences` cannot fix it: the mapping
restructures document paths, so FR-ARCH-0049 deliberately emits no
folder-level pair, and per-document pairs do not match a glob string.

Add `pluginReplaceLiterals(pairs)` (FR-ARCH-0058) — a generic processor
performing exact literal substitution, composed via `buildPipeline`'s
`extraAfterIndexes` only into the Codex and Antigravity pipelines. It runs
before the bootstrap assembler, which reads bodies from frames, so hook
payloads inherit the correction. Deliberately plain substring substitution
with no boundary, regex, or dot-directory guards: the target is prose, not a
path token. Keyed on the long literal so the unrelated bare `workflows/*.md`
in `skills/rosetta/README.md` stays untouched.

An earlier iteration did this with a `PluginSpec.literalRewritePairs` field
folded into `buildRenamePairs`. That was reverted: it added a field only two
of seven specs used, put prose substitution behind path-token matching
semantics, and pushed target-specific data into a lookup consulted by every
target. Generated output is identical either way.

Normalize the two r2 `plugin-files-mode.md` bullets (`, ` to `/`, drop "in")
so both releases carry one identical literal instead of two variants.

Remove the obsolete bootstrap prefix. Hooks are small now and
`get_context_instructions` is no longer used in this flow, so the fixed
lead-in string is dead weight. `BOOTSTRAP_PREFIX` and its application are
gone, along with the orphaned `isLead` field on `BootstrapEntryRef` and all
nine manifest entries. Leading-newline stripping now applies to every entry
rather than only the lead — all bodies come from `stripFrontmatter` and all
carried one, so stripping just the first was arbitrary. This also drops the
positional-lead semantics QF-1 flagged. FR-HOOK-0003 is Deprecated;
GLOSSARY, ASSUMPTIONS and NFR-0004 updated. Entry counts are unchanged
(Claude 9/5, Copilot 9/5, Codex 8/4) — only the lead entry's content shrinks.

Trim leading blank lines from emitted phase files. `stripFrontmatter` returns
a body starting with a newline, so every phase document opened with a blank
line. Trimmed at the phase-write site; `stripFrontmatter` itself is unchanged
because the bootstrap payload depends on its current shape.

Codex manifest: `Rosetta 2.0` to `Rosetta 3`, and `defaultPrompt` replaced
with example starting prompts.

Fix a misleading manifest comment: all five split `bootstrap-*` entries are
r2-only, not just `bootstrap-hitl-questioning`; r3 consolidates them into a
single `bootstrap-alwayson`.

Suite at 49 files / 572 tests. New coverage includes the long-vs-bare literal
negative case, proof that depth rather than basename drives the relocation
discriminant, prefix-absence across all assembler suites, and two tests
pinning the deliberate absence of path-token boundary guards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e removed prefix

FR-HOOK-0009 still promised an explicit, non-positional lead designation. That
designation existed only to place the bootstrap prefix; with the prefix gone
the `isLead` flag was removed rather than left as a field no behavior reads,
so the requirement no longer matched the code.

Restate FR-HOOK-0009: manifest order governs payload sequence and determinism
only, no entry carries a lead designation, and the leading-newline strip
applies uniformly to every entry. Replace its prefix-placement acceptance
criterion and move it to Implemented with file/test evidence.

Also reconcile the remaining references: FR-HOOK-0001's rationale no longer
claims the manifest fixes prefix placement; FR-HOOK-0003's notes describe the
strip as uniform rather than lead-only; FR-HOOK-0007 says the plugin-root
entry is not folded into any document's body rather than the lead's;
ASSUMPTIONS QF-1 is marked moot; GLOSSARY drops the lead-only phrasing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two conflicts, both in the Codex plugin manifest (preserved source and its
generated copy). Each side had independently corrected the stale
"Rosetta 2.0" title.

Resolved as a three-way merge rather than picking a side:
- `version` 3.1.1 from main's release bump
- `longDescription` "Rosetta 3 for Codex" from this branch (user decision;
  main had "3.0")
- `defaultPrompt` example starting prompts from this branch

MEMORY.md auto-merged, keeping both sides' entries.

Main's new `security-flow` workflow and its 8 phase documents pass through
this branch's workflow-to-skill transform correctly: Codex and Antigravity
emit `skills/security-flow/SKILL.md` plus 8 frontmatter-stripped phase files,
while Claude keeps `workflows/security-flow.md`.

rosettify-plugins 49 files / 572 tests, hooks 33 files / 1142 tests, build and
typecheck clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add the Plugin Generator entry for issue #162 / PR #164: the generalized
workflow-to-skill transform, the four defects fixed alongside it, the
requirement dispositions, and the corrected session-hook entry counts.

Also correct a stale figure in the 2026-06-05 re-implementation entry, which
recorded the r3 bootstrap payload as 8 entries. It was never 8 — r3
consolidates the five split `bootstrap-*` rules into one `bootstrap-alwayson.md`
and the absent basenames are skipped, giving 5.

docs/ARCHITECTURE.md and its docs/web mirror were already updated in the
feature commits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Composing a conflicted line per-field rather than picking a side; generated
plugins/ conflicts mirroring their preserved source; version drift surviving a
clean merge; and re-verifying main's new content against the branch's
generation changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ript, regenerate

core-antigravity's manifest was stranded at 3.1.0 while the other four moved to
3.1.1, because scripts/bump_versions.sh never listed it — its manifest sits at
the plugin root rather than under a *-plugin/ config folder, so it was missed
when the list was written. Added to the script so future bumps cover it.

Bumped the preserved source to 3.1.1 and regenerated all seven plugins with
`--release r3 --deterministic-hooks false`, matching pre_commit.py.

The regenerated tree also picks up everything merged from main and this
branch: main's security-flow workflow now emits as a Codex/Antigravity skill,
the plugin-files-mode glob doc reads `skills/*-flow/SKILL.md` for those two
targets and stays `workflows/*.md` for Claude, phase files carry no frontmatter
or leading blank line, no bootstrap prefix remains anywhere, and
.agents/workflows/ is gone.

src/rosettify-plugins/package.json stays at 3.2.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@isolomatov-gd
isolomatov-gd requested a review from omaiesh as a code owner July 29, 2026 01:50
Signed-off-by: isolomatov-gd <isolomatov@griddynamics.com>
@isolomatov-gd isolomatov-gd self-assigned this Jul 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📋 Prompt Quality Validation Report

❌ Validation Failed

The full markdown report and raw JSON output are available in the workflow artifacts for 5 days.


Files With Issues

  • instructions/r2/core/rules/plugin-files-mode.md: 2 issue(s)

📄 instructions/r2/core/rules/plugin-files-mode.md

⚠️ Issues Found

Severity Gate Details
High Reference Integrity Problem:
The rewording turned this prose line into an exact-match build key. The generator pair keys on the full literal WORKFLOW/COMMAND workflows/*.md including the prefix, so the old wording `WORKFLOW, COMMAND in `workflows/*.md did not match and the new wording does. Nothing in the file marks the line as generator-coupled, the substitution step reports nothing when a pair matches zero times, and the tests that cover it assert against inline fixtures that contain the literal rather than against this file. Any later edit to spacing, the comma, or the word order silently ships a workflows/*.md glob into the Codex and Antigravity plugins, which have no workflows/ folder.
Reason:
The failure is silent at every step, so the tests stay green while the shipped plugin goes stale. An agent that globs a folder which does not exist finds nothing and then tends to rebuild workflow content from memory, which this same bootstrap forbids.
Solution:
Do not change the prompt wording; it is correct and now matches r3. Add the guard in the generator instead: fail the build when a configured literal pair matches zero times, and add a test that reads the real instructions/r2/core/rules/plugin-files-mode.md and asserts the pair's source literal is present. Run that test for r2 as well as the default release, since the CLI defaults to r3 and r2 is the release this change touches.
High Conflict Resolution Problem:
The reworded line WORKFLOW/COMMAND workflows/*.md is the exact string the plugin generator rewrites to `WORKFLOW/COMMAND `skills/*-flow/SKILL.md for the Codex and Antigravity targets. The earlier # COMMAND ALIASES - PLUGIN MODE section in the same file is not rewritten, so it still says LIST workflows IN KB => list workflows/ folder, and the # LOCAL FILES MODE FOR PLUGINS section still says Plugin structure: skills/, agents/, workflows/, rules/``. In those two shipped plugins the always-on bootstrap now tells the agent two different things about where workflows live. Before this change both sections said workflows/ and agreed, so the file was consistent even though it pointed at a folder those targets no longer create.
Reason:
This file is always on and never compacted, so both statements stay in context at once. When one always-on section contradicts another, the agent picks one at random or tries both, which makes workflow lookup non-deterministic across sessions in the two targets where `workflows/` does not exist.
Solution:
Keep the new wording, and make the other two sections agree per target. Either add generator literal pairs for the `LIST workflows IN KB` alias line and the `Plugin structure:` list so all three sections are rewritten together, or drop the folder name from those two lines so only `# ADDITIONAL SOURCES IN PLUGIN` states locations and the alias line just names the artifact type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex: workflow is not visible

2 participants