Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
32f8db2
refactor(core): route list/view/archive through planning-home resolver
joctaTorres Jun 10, 2026
a736dcb
feat(planning-home): lazy parent resolution and module-name derivation
joctaTorres Jun 10, 2026
f4ea39a
feat(planning-home): discover nested modules from root
joctaTorres Jun 10, 2026
a47dbf1
feat(planning-home): reconcile discovered modules against the registry
joctaTorres Jun 10, 2026
bae91f6
feat(cli): add shared --module option to address modules from the root
joctaTorres Jun 10, 2026
da2fb68
feat(list): aggregate root list across root and discovered modules
joctaTorres Jun 10, 2026
549bd28
feat(standards): layer standards across the parent chain
joctaTorres Jun 10, 2026
6d87871
test(archive): verify module changes archive into the module store
joctaTorres Jun 10, 2026
c480178
feat(features): regenerate reverse standard links in the defining home
joctaTorres Jun 10, 2026
667ecd3
test(e2e): monorepo fixture covering nested-planning-home scenarios
joctaTorres Jun 10, 2026
2e4384b
test(e2e): pin single-home backward compatibility
joctaTorres Jun 10, 2026
529ecb7
docs(ratchet): add nested-planning-homes change artifacts
joctaTorres Jun 10, 2026
a4566de
Merge branch 'main' into monorepo
joctaTorres Jun 17, 2026
7cdf601
refactor(planning-home): route platform-path normalization through to…
joctaTorres Jun 17, 2026
4e59c8f
fix(module-discovery): one duplicate-name policy via discoverModulesSafe
joctaTorres Jun 17, 2026
7cda082
refactor(list): extract collectModuleChanges from list.execute
joctaTorres Jun 17, 2026
89467d4
refactor(features-apply): extract regenerateLayeredReverseLinks
joctaTorres Jun 17, 2026
fdf5723
refactor(project-config): extract per-field parse helpers
joctaTorres Jun 17, 2026
e7bb867
refactor(archive): extract --module resolution from archive.execute
joctaTorres Jun 17, 2026
c964289
fix(module-discovery): flag approximate gitignore handling in error
joctaTorres Jun 17, 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
2 changes: 2 additions & 0 deletions .ratchet/changes/nested-planning-homes/.ratchet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: ratchet
created: 2026-06-10
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Feature: Module discovery from the root planning home
As a developer at the root of a monorepo
I want ratchet to discover nested .ratchet directories on the filesystem
So that new modules are visible without manual registration, while a registry can lint the expected layout

Background:
Given a repository with a .ratchet directory at the repo root

Scenario: Nested planning homes are discovered by filesystem scan
Given nested .ratchet directories exist at "packages/api" and "packages/web"
And the root config declares no module registry
When I run "ratchet list" from the repo root
Then modules "packages/api" and "packages/web" are discovered
And no registry warnings are shown

Scenario: Module names default to the path relative to the repo root
Given a nested .ratchet directory exists at "packages/api"
When the module is discovered
Then its module name is "packages/api"

Scenario: A module can override its name in its own config
Given a nested .ratchet directory exists at "packages/api"
And "packages/api/.ratchet/config.yaml" declares name "api"
When the module is discovered
Then its module name is "api"

Scenario: Discovered module missing from the registry produces a warning
Given the root config registers modules ["packages/api"]
And nested .ratchet directories exist at "packages/api" and "packages/web"
When I run "ratchet list" from the repo root
Then module "packages/web" is still included in the results
And a warning reports that "packages/web" is not registered

Scenario: Registered module missing on disk produces a warning
Given the root config registers modules ["packages/api", "packages/legacy"]
And a nested .ratchet directory exists only at "packages/api"
When I run "ratchet list" from the repo root
Then a warning reports that registered module "packages/legacy" has no .ratchet directory
And the command still succeeds

Scenario: Discovery does not descend into nested modules or ignored directories
Given a nested .ratchet directory exists at "packages/api"
And a directory "node_modules" containing a stray .ratchet directory
When modules are discovered from the repo root
Then "node_modules" is not reported as a module
And no .ratchet directory nested below "packages/api" is reported as a separate module
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Feature: Addressing a module from the root
As a developer working at the monorepo root
I want to target a specific module's planning home with a --module flag
So that I can manage module changes without changing directory

Background:
Given a repository with a .ratchet directory at the repo root
And a nested .ratchet directory at "packages/api" named "api"

Scenario: Creating a change inside a module from the root
Given the current working directory is the repo root
When I run "ratchet new change add-auth --module api"
Then the change is created at "packages/api/.ratchet/changes/add-auth"
And the change uses the module's default schema

Scenario: Reading status of a module change from the root
Given a change "add-auth" exists in module "api"
When I run "ratchet status --change add-auth --module api" from the repo root
Then the reported planning home root is "packages/api"
And the reported change root is "packages/api/.ratchet/changes/add-auth"

Scenario: An unknown module name fails with the list of known modules
When I run "ratchet status --change add-auth --module billing" from the repo root
Then the command fails with an error naming "billing" as unknown
And the error lists the discovered module names

Scenario: Omitting --module keeps current nearest-wins behavior
Given a change "root-change" exists in the root planning home
When I run "ratchet status --change root-change" from the repo root
Then the resolved planning home root is the repo root
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Feature: Module-local feature stores
As a maintainer of a monorepo
I want archived features to land in the module's own feature store
So that each module stays self-contained and its behavior record travels with its code

Background:
Given a repository with a .ratchet directory at the repo root
And a nested .ratchet directory at "packages/api" named "api"

Scenario: Archiving a module change materializes features into the module store
Given module "api" contains a completed change "add-auth" with feature "features/auth/login.feature"
When the change "add-auth" is archived
Then "packages/api/.ratchet/features/auth/login.feature" exists
And the root feature store does not contain "auth/login.feature"
And the change is moved to "packages/api/.ratchet/changes/archive"

Scenario: Archiving a root change materializes features into the root store
Given the root planning home contains a completed change "upgrade-ci" with feature "features/ci/pipeline.feature"
When the change "upgrade-ci" is archived
Then ".ratchet/features/ci/pipeline.feature" exists at the repo root
And no module feature store is modified

Scenario: Standard links for an inherited standard are written into the defining home
Given the root standards library contains a standard tagged "testing"
And module "api" archives a change declaring standards ["testing"] with feature "features/auth/login.feature"
When standard links are materialized
Then the forward link sidecar is written in the module's feature store
And the "Implemented by" block of the root standard "testing" lists the feature qualified by module name "api"

Scenario: Standard links for a module-local standard stay within the module
Given module "api" standards library contains a standard tagged "api-versioning"
And module "api" archives a change declaring standards ["api-versioning"]
When standard links are materialized
Then the "Implemented by" block is regenerated in "packages/api/.ratchet/standards"
And no file under the root .ratchet directory is modified
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Feature: Nearest planning home wins
As a developer in a monorepo
I want ratchet to resolve the closest .ratchet directory to where I work
So that commands run inside a sub-module operate on that module without extra flags

Background:
Given a repository with a .ratchet directory at the repo root
And a nested .ratchet directory at "packages/api"

Scenario: Command run inside a module resolves the module's planning home
Given the current working directory is "packages/api/src"
When I run "ratchet status"
Then the resolved planning home root is "packages/api"
And changes are read from "packages/api/.ratchet/changes"

Scenario: Command run at the repo root resolves the root planning home
Given the current working directory is the repo root
When I run "ratchet status"
Then the resolved planning home root is the repo root
And changes are read from ".ratchet/changes"

Scenario: Single-home repositories behave exactly as before
Given a repository whose only .ratchet directory is at the repo root
And the current working directory is any subdirectory of the repo
When I run any ratchet command
Then the resolved planning home root is the repo root
And no module-related warnings or output are shown

Scenario: list, view, and archive obey walk-up resolution
Given the current working directory is "packages/api/src"
When I run "ratchet list"
Then the listed changes come from "packages/api/.ratchet/changes"
And the command does not read ".ratchet" relative to the current working directory
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Feature: Root aggregation of module changes
As a developer at the monorepo root
I want root-level listing to include changes from nested modules
So that I can see all in-flight work across the repo in one place

Background:
Given a repository with a .ratchet directory at the repo root
And a nested .ratchet directory at "packages/api" named "api"
And a nested .ratchet directory at "packages/web" named "web"

Scenario: Root list shows root and module changes labeled by module
Given the root planning home contains a change "upgrade-ci"
And module "api" contains a change "add-auth"
And module "web" contains a change "dark-mode"
When I run "ratchet list" from the repo root
Then the output includes "upgrade-ci" attributed to the root
And the output includes "add-auth" attributed to module "api"
And the output includes "dark-mode" attributed to module "web"

Scenario: Module-level list stays scoped to the module
Given module "api" contains a change "add-auth"
And the root planning home contains a change "upgrade-ci"
When I run "ratchet list" from inside "packages/api"
Then the output includes "add-auth"
And the output does not include "upgrade-ci"

Scenario: A module's broken config does not break root aggregation
Given module "api" has an unparseable .ratchet/config.yaml
And module "web" contains a change "dark-mode"
When I run "ratchet list" from the repo root
Then the output includes "dark-mode" attributed to module "web"
And a warning reports that module "api" could not be loaded
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Feature: Standards inheritance across nested planning homes
As a maintainer of a monorepo
I want module changes to see root standards plus their own module standards
So that org-wide rules propagate while modules can specialize

Background:
Given a repository with a .ratchet directory at the repo root
And a nested .ratchet directory at "packages/api" named "api"

Scenario: Module instructions include inherited root standards
Given the root standards library contains a standard tagged "testing"
And module "api" has no standards of its own
When I run "ratchet instructions plan --change add-auth --module api"
Then the standards in the output include "testing"

Scenario: Module standards are added on top of root standards
Given the root standards library contains a standard tagged "testing"
And module "api" standards library contains a standard tagged "api-versioning"
When instructions are generated for a change in module "api"
Then the standards in the output include both "testing" and "api-versioning"

Scenario: On tag collision the module standard shadows the root standard
Given the root standards library contains a standard tagged "testing" with content "root version"
And module "api" standards library contains a standard tagged "testing" with content "api version"
When instructions are generated for a change in module "api"
Then exactly one standard tagged "testing" is included
And its content is "api version"

Scenario: Root changes see only root standards
Given the root standards library contains a standard tagged "testing"
And module "api" standards library contains a standard tagged "api-versioning"
When instructions are generated for a change in the root planning home
Then the standards in the output include "testing"
And the standards in the output do not include "api-versioning"

Scenario: Standard tags declared by a module change validate against the layered set
Given the root standards library contains a standard tagged "testing"
And a change in module "api" declares standards ["testing"]
When the change's standard tags are validated
Then validation succeeds even though "testing" is not defined in the module
Loading