* test(#4256): pin todos as root-scoped under workstreams (RED) * fix(#4256): resolve todos from the root via todosDir everywhere * chore(#4256): changeset fragment (pr number to backfill) * chore(#4256): backfill PR number in changeset --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -304,6 +304,7 @@ interface PlanningPaths {
|
||||
requirements: string;
|
||||
debug: string;
|
||||
quick: string;
|
||||
todos: string;
|
||||
}
|
||||
|
||||
// #2142: the quick-task directory. Exported as its own function (not only as a
|
||||
@@ -316,6 +317,33 @@ function quickDirFrom(planningBase: string): string {
|
||||
return path.join(planningBase, 'quick');
|
||||
}
|
||||
|
||||
// #4256: the todos directory — deliberately ROOT-SCOPED, unlike every other
|
||||
// planningPaths key. Todos are shared project state by construction: the
|
||||
// migrateToWorkstreams contract keeps them among the shared files that "stay
|
||||
// in place" at .planning/todos/ (workstream.cts), and every workflow writer
|
||||
// writes that literal cwd-relative root path. The six todos readers
|
||||
// previously hand-composed `path.join(planningDir(cwd), 'todos', ...)`,
|
||||
// which silently re-scoped to .planning/workstreams/<ws>/todos/ — a
|
||||
// directory nothing creates — under a workstream, so todos went invisible
|
||||
// and audit-open passed the milestone-close gate vacuously. Same
|
||||
// two-composers-of-one-path shape the `debug` (#3149) and `quick` (#2142)
|
||||
// keys were introduced to eliminate (DEFECT.GENERATIVE-FIX).
|
||||
//
|
||||
// Exported as its own function pair (not only as a `planningPaths` key)
|
||||
// because `audit.cts`'s `scanTodos`/`cmdAuditAcknowledge` consume an
|
||||
// already-resolved todos base rather than a `cwd`, mirroring how #2142
|
||||
// exported `quickDirFrom` for `scanQuickTasks`. `todosDir` takes NO ws/project
|
||||
// parameter — todos have no workstream- or project-scoped form anywhere, so
|
||||
// there is no discriminator to thread. This is also the single root #4327's
|
||||
// future filename-containment guard should enforce against.
|
||||
function todosDirFrom(planningBase: string): string {
|
||||
return path.join(planningBase, 'todos');
|
||||
}
|
||||
|
||||
function todosDir(cwd: string): string {
|
||||
return todosDirFrom(planningRoot(cwd));
|
||||
}
|
||||
|
||||
function planningPaths(cwd: string, ws?: string | null): PlanningPaths {
|
||||
const base = planningDir(cwd, ws);
|
||||
return {
|
||||
@@ -332,6 +360,11 @@ function planningPaths(cwd: string, ws?: string | null): PlanningPaths {
|
||||
debug: path.join(base, 'debug'),
|
||||
// #2142: quick-task directory, composed via the shared quickDirFrom helper.
|
||||
quick: quickDirFrom(base),
|
||||
// #4256: todos directory — deliberately ROOT-scoped while the rest of
|
||||
// this record follows the active workstream/project (todos are shared
|
||||
// project state per the migrateToWorkstreams contract), composed via the
|
||||
// shared todosDir helper so this key and every direct caller agree.
|
||||
todos: todosDir(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -638,6 +671,8 @@ export = {
|
||||
listAvailableWorkstreams,
|
||||
planningPaths,
|
||||
quickDirFrom,
|
||||
todosDirFrom,
|
||||
todosDir,
|
||||
withPlanningLock,
|
||||
getActiveWorkstream,
|
||||
peekActiveWorkstream,
|
||||
|
||||
Reference in New Issue
Block a user