@smartmemory/compose 0.2.16-beta → 0.2.17-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/feature-validator.js +34 -17
- package/package.json +1 -1
package/lib/feature-validator.js
CHANGED
|
@@ -300,6 +300,15 @@ function finding(severity, kind, code, detail, source) {
|
|
|
300
300
|
return f;
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
+
// A code owned by another repo (matches a declared externalPrefix, e.g. STRAT-*)
|
|
304
|
+
// is a cross-repo REFERENCE. Compose can validate that the reference resolves, but
|
|
305
|
+
// not the external feature's local artifacts, completion records, folder layout,
|
|
306
|
+
// row-schema, or authoritative status — all of which live in the owning repo. The
|
|
307
|
+
// per-feature local-correspondence checks consult this and skip such codes.
|
|
308
|
+
function isExternalCode(code, ctx) {
|
|
309
|
+
return !!code && (ctx?.externalPrefixes || []).some((p) => code.startsWith(p));
|
|
310
|
+
}
|
|
311
|
+
|
|
303
312
|
// ---------------------------------------------------------------------------
|
|
304
313
|
// Per-feature checks
|
|
305
314
|
// ---------------------------------------------------------------------------
|
|
@@ -373,7 +382,7 @@ function runSchemaChecks(fctx, ctx, findings) {
|
|
|
373
382
|
}
|
|
374
383
|
}
|
|
375
384
|
}
|
|
376
|
-
if (roadmap) {
|
|
385
|
+
if (roadmap && !isExternalCode(code, ctx)) {
|
|
377
386
|
const v = getValidator(ROADMAP_ROW_SCHEMA);
|
|
378
387
|
const r = v.validateRoot(roadmap);
|
|
379
388
|
if (!r.valid) {
|
|
@@ -401,8 +410,11 @@ function projectToVisionStatus(s) {
|
|
|
401
410
|
return s === 'PARTIAL' ? 'IN_PROGRESS' : s;
|
|
402
411
|
}
|
|
403
412
|
|
|
404
|
-
function runStateMismatchChecks(fctx, findings) {
|
|
413
|
+
function runStateMismatchChecks(fctx, ctx, findings) {
|
|
405
414
|
const { code, roadmap, vision, featureJson } = fctx;
|
|
415
|
+
// Compose is not the authority on an external feature's status — its ROADMAP/
|
|
416
|
+
// vision rows are cross-repo mirrors that may legitimately lag the owning repo.
|
|
417
|
+
if (isExternalCode(code, ctx)) return;
|
|
406
418
|
const rStatus = normalizeStatus(roadmap?.status);
|
|
407
419
|
const fStatus = normalizeStatus(featureJson?.status);
|
|
408
420
|
const vStatus = normalizeStatus(vision?.status);
|
|
@@ -471,21 +483,18 @@ function runFolderRoadmapLinkageChecks(fctx, ctx, findings) {
|
|
|
471
483
|
const { code, folder, roadmap, vision, featureJson } = fctx;
|
|
472
484
|
const rStatus = normalizeStatus(roadmap?.status);
|
|
473
485
|
|
|
486
|
+
// Externally-owned codes (e.g. STRAT-*) are cross-repo references whose folder,
|
|
487
|
+
// artifacts, and row layout live in the owning project — folder-linkage does not
|
|
488
|
+
// apply, so skip the whole check (row↔folder, folder↔row, empty-folder).
|
|
489
|
+
if (isExternalCode(code, ctx)) return;
|
|
490
|
+
|
|
474
491
|
if (roadmap && !folder) {
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
//
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
if (isExternal) {
|
|
482
|
-
// no finding — out of scope for folder-linkage validation
|
|
483
|
-
} else if (rStatus === 'IN_PROGRESS') {
|
|
484
|
-
// Severity model for missing folder:
|
|
485
|
-
// IN_PROGRESS → error (active work without a tracking artifact)
|
|
486
|
-
// PARTIAL / BLOCKED → warning (sub-tickets may live elsewhere; partial progress)
|
|
487
|
-
// PLANNED → warning (un-started work)
|
|
488
|
-
// COMPLETE / SUPERSEDED / KILLED / PARKED / unknown → warning (historical baseline)
|
|
492
|
+
// Severity model for missing folder:
|
|
493
|
+
// IN_PROGRESS → error (active work without a tracking artifact)
|
|
494
|
+
// PARTIAL / BLOCKED → warning (sub-tickets may live elsewhere; partial progress)
|
|
495
|
+
// PLANNED → warning (un-started work)
|
|
496
|
+
// COMPLETE / SUPERSEDED / KILLED / PARKED / unknown → warning (historical baseline)
|
|
497
|
+
if (rStatus === 'IN_PROGRESS') {
|
|
489
498
|
findings.push(finding('error', 'ROADMAP_ROW_WITHOUT_FOLDER', code,
|
|
490
499
|
`ROADMAP row status is IN_PROGRESS (active work) but no folder exists`));
|
|
491
500
|
} else {
|
|
@@ -519,6 +528,8 @@ function runFolderRoadmapLinkageChecks(fctx, ctx, findings) {
|
|
|
519
528
|
function runArtifactLinkChecks(fctx, ctx, findings) {
|
|
520
529
|
const { code, folder, featureJson } = fctx;
|
|
521
530
|
if (!folder) return;
|
|
531
|
+
// External features keep their design/report/artifacts in the owning repo.
|
|
532
|
+
if (isExternalCode(code, ctx)) return;
|
|
522
533
|
const featureRootArg = ctx.paths.features;
|
|
523
534
|
const am = new ArtifactManager(featureRootArg);
|
|
524
535
|
let assessment = null;
|
|
@@ -607,6 +618,9 @@ function runCrossFeatureRefChecks(fctx, ctx, findings) {
|
|
|
607
618
|
|
|
608
619
|
function runCoherenceChecks(fctx, ctx, findings) {
|
|
609
620
|
const { code, featureJson } = fctx;
|
|
621
|
+
// External features record their changelog/journal in the owning repo, so
|
|
622
|
+
// compose can't (and shouldn't) assert those entries exist here.
|
|
623
|
+
if (isExternalCode(code, ctx)) return;
|
|
610
624
|
// COMPLETION_WITHOUT_CHANGELOG — check at project level, but per-feature too
|
|
611
625
|
const status = effectiveStatus(fctx, ctx);
|
|
612
626
|
if (status === 'COMPLETE' || status === 'PARTIAL') {
|
|
@@ -663,6 +677,9 @@ function runChangelogReferenceCheck(ctx, findings) {
|
|
|
663
677
|
let m;
|
|
664
678
|
while ((m = headerRe.exec(text))) {
|
|
665
679
|
const code = m[1];
|
|
680
|
+
// External codes (e.g. STRAT-*) are legitimately referenced in compose's
|
|
681
|
+
// CHANGELOG without a local folder/row — their home is the owning repo.
|
|
682
|
+
if (isExternalCode(code, ctx)) continue;
|
|
666
683
|
if (!ctx.roadmapByCode.has(code) && !ctx.foldersByCode.has(code) && !ctx.visionByCode.has(code)) {
|
|
667
684
|
// Downgraded from error: many shipped features have CHANGELOG entries without
|
|
668
685
|
// ROADMAP rows or vision-state items (legacy pattern where CHANGELOG is the
|
|
@@ -729,7 +746,7 @@ export async function validateFeature(cwd, code, options = {}) {
|
|
|
729
746
|
}
|
|
730
747
|
|
|
731
748
|
runSchemaChecks(fctx, ctx, findings);
|
|
732
|
-
runStateMismatchChecks(fctx, findings);
|
|
749
|
+
runStateMismatchChecks(fctx, ctx, findings);
|
|
733
750
|
runFolderRoadmapLinkageChecks(fctx, ctx, findings);
|
|
734
751
|
runArtifactLinkChecks(fctx, ctx, findings);
|
|
735
752
|
runCrossFeatureRefChecks(fctx, ctx, findings);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartmemory/compose",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17-beta",
|
|
4
4
|
"description": "Structured AI dev pipeline — goal-to-product orchestration with gates, iteration loops, and feature lifecycle management.",
|
|
5
5
|
"author": "SmartMemory",
|
|
6
6
|
"license": "MIT",
|