Skip to content

Port the story filer to TypeScript #353

Description

@sameera

Epic: Port the story filer to TypeScript

⚠️ Utilization risk: assessed L (1–2 weeks). Fills the sprint with no slack for overruns. Watch for scope creep.

Description

The story filer is the capability that turns a folder of STORY-*.md work items into GitHub issues. Every planning stage that files anything reaches it: /nxs.epic files an epic's stories through it and files backlog stubs through it, and /nxs.close files deferred scope through it. It is the last large piece of Nexus still written in Python, and while it stays there the release keeps declaring a Python interpreter as a runtime requirement — so a stage can fail on a machine where python3 resolves to the wrong thing, at the moment a lead is filing a batch of issues.

The toolkit shell and the shared delivery-configuration resolver already moved across (#351). Their TypeScript home stands beside a registry that still delegates create-story to the Python module. This epic replaces that delegation with a native implementation: the three passes the filer runs — create every issue, wire the native blocked_by edges between them, rewrite the surviving authoring refs in the bodies to issue numbers — plus the preflight that decides a batch is legal before anything irreversible happens, and the resume ledger that makes an interrupted batch safe to re-run.

The bar is behaviour preservation, not improvement. This is the one capability in Nexus whose failure mode is duplicate GitHub issues, so its resumability and idempotence are the point, not a detail. Every flag, every line of output and every exit code stays as it is, because component bodies and pipeline stages invoke it by name and read its ⚠️ INCOMPLETE contract. The existing Python tests are the specification: they are carried across rather than reinvented, so a divergence surfaces as a failing test instead of as a half-filed batch in someone's repository.

Success Metrics

  • nexus-gh create-story runs a full batch to completion with no Python interpreter process spawned.
  • The behaviours asserted by the existing Python tests — test_backlog_stubs, test_body_ref_rewrite, test_deferred_scope_stubs, test_literal_dependency_refs, and the story filer half of test_writeback_integration — are asserted by TypeScript tests over the same cases.
  • A batch of M work items interrupted after N issues have been created, then re-run with the identical command, creates exactly M − N issues and zero duplicates.
  • Every flag the capability accepts today is accepted with the same meaning, and every exit code is unchanged: 0 for a complete run and for an empty folder, non-zero for a refused preflight and for an incomplete run.
  • The story filer source defines no function of its own for reading configuration, resolving classification or project targets, upserting labels, probing issue types, or writing the settings block back — each is reached through the shared module ported in Port the toolkit shell and the shared delivery-config resolver to TypeScript #351, and a test asserts that.

Personas

Per docs/product/context.md.

Terminology

Two label vocabularies meet in this capability and are easy to conflate. Throughout this epic:

  • work item — one STORY-*.md file in the target folder, the unit the filer turns into an issue. "Work item" is the artifact on disk; "story" is what it becomes on GitHub. Where an acceptance criterion says "the story", it means the work item's filed outcome.
  • canonical classification label — the single label the run applies to every issue it creates, denoting what kind of issue this batch is. It defaults to the resolved story label and is overridden by --classification-label, which is how a caller files a batch of backlog stubs instead of a batch of stories.
  • unplanned label — a different label, resolved through the shared resolver, that marks an issue as scope identified but not yet planned. It reaches an issue through a work item's own labels: frontmatter, never through the classification path. Story 1's refusal is about this label alone.
  • resume ledger — the JSON file the run writes into the target folder recording which ref became which issue. The flag that preserves it is spelled --keep-manifest; the name is frozen by the behaviour-preservation bar, so the flag and the ledger are the same artifact under two names.
  • settings block — the publishing configuration in the repository's settings file, read through the shared resolver and seeded back through the shared writer. "Publishing configuration", "the github block" and "the settings file" all refer to it.

Assumptions

Out of Scope

Open Questions

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicEpic (created by nxs-gh-create-epic)in-progressDesign filed; approval is the close of the record sub-issue

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions