@magic-spells/constellation 0.1.0 → 0.2.0
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/README.md +41 -4
- package/dist/cli/index.js +62 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/update-check.d.ts +6 -0
- package/dist/cli/update-check.js +70 -0
- package/dist/cli/update-check.js.map +1 -0
- package/dist/{mcp → core}/git.d.ts +19 -0
- package/dist/{mcp → core}/git.js +59 -2
- package/dist/core/git.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/repos.d.ts +40 -0
- package/dist/core/repos.js +93 -0
- package/dist/core/repos.js.map +1 -0
- package/dist/core/resolve.js +10 -1
- package/dist/core/resolve.js.map +1 -1
- package/dist/core/scaffold.d.ts +16 -3
- package/dist/core/scaffold.js +30 -7
- package/dist/core/scaffold.js.map +1 -1
- package/dist/core/sync.d.ts +28 -0
- package/dist/core/sync.js +85 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/core/types.d.ts +12 -0
- package/dist/mcp/server.js +434 -38
- package/dist/mcp/server.js.map +1 -1
- package/dist/serve/server.js +28 -4
- package/dist/serve/server.js.map +1 -1
- package/docs/001-file-format.md +25 -0
- package/docs/002-mcp.md +56 -7
- package/examples/constellation/plan.md +1 -1
- package/package.json +3 -1
- package/schemas/plan.json +27 -0
- package/skill/SKILL.md +131 -1
- package/skill/methodology.md +228 -0
- package/skill/types/plan.md +19 -0
- package/viewer/dist/assets/{arc-Kj6pF3JI.js → arc-CMMRgIq9.js} +1 -1
- package/viewer/dist/assets/architecture-7EHR7CIX-Cbb-syEI.js +1 -0
- package/viewer/dist/assets/{architectureDiagram-3BPJPVTR-C5bZdErB.js → architectureDiagram-3BPJPVTR-CB5p_qlN.js} +1 -1
- package/viewer/dist/assets/{blockDiagram-GPEHLZMM-C1Q6l6fE.js → blockDiagram-GPEHLZMM-DpnMj_e6.js} +1 -1
- package/viewer/dist/assets/{c4Diagram-AAUBKEIU-BmM6Tmtq.js → c4Diagram-AAUBKEIU-f91ngVN8.js} +1 -1
- package/viewer/dist/assets/channel-C2bkEQHQ.js +1 -0
- package/viewer/dist/assets/{chunk-2J33WTMH-z09tLTpZ.js → chunk-2J33WTMH-y7Pz5tMO.js} +1 -1
- package/viewer/dist/assets/{chunk-3OPIFGDE-BynpXh1r.js → chunk-3OPIFGDE-Ir_ghIUQ.js} +1 -1
- package/viewer/dist/assets/{chunk-4BX2VUAB-CDOVuPyG.js → chunk-4BX2VUAB-BTPyM1ux.js} +1 -1
- package/viewer/dist/assets/{chunk-55IACEB6-nBwigOgn.js → chunk-55IACEB6-CtNd8e4Y.js} +1 -1
- package/viewer/dist/assets/{chunk-5ZQYHXKU-Bxe5xIy_.js → chunk-5ZQYHXKU-Dd3yz721.js} +1 -1
- package/viewer/dist/assets/{chunk-727SXJPM-DZmTgL68.js → chunk-727SXJPM-CAM8mGbv.js} +1 -1
- package/viewer/dist/assets/{chunk-AQP2D5EJ-B7wr_Owx.js → chunk-AQP2D5EJ-C3nW9Uve.js} +1 -1
- package/viewer/dist/assets/{chunk-BSJP7CBP-DbAKfVCK.js → chunk-BSJP7CBP-r6MRPvAH.js} +1 -1
- package/viewer/dist/assets/{chunk-CSCIHK7Q-C0rsBwqP.js → chunk-CSCIHK7Q-Cn-ZTxsS.js} +1 -1
- package/viewer/dist/assets/{chunk-FMBD7UC4-BAtzt0wv.js → chunk-FMBD7UC4-5axXeZJa.js} +1 -1
- package/viewer/dist/assets/{chunk-KSCS5N6A-CXXwf52I.js → chunk-KSCS5N6A-BwmNx0l0.js} +1 -1
- package/viewer/dist/assets/{chunk-L5ZTLDWV-DS4vRI1U.js → chunk-L5ZTLDWV-C2YNkUjB.js} +1 -1
- package/viewer/dist/assets/chunk-LZXEDZCA-CznuDgQD.js +2 -0
- package/viewer/dist/assets/{chunk-ND2GUHAM-CUSnPl8t.js → chunk-ND2GUHAM-CokDnghi.js} +1 -1
- package/viewer/dist/assets/{chunk-NZK2D7GU-Dh986nJk.js → chunk-NZK2D7GU-aaU0v4QE.js} +1 -1
- package/viewer/dist/assets/{chunk-O5CBEL6O-JAEZ_pS6.js → chunk-O5CBEL6O-ByfKhkZf.js} +1 -1
- package/viewer/dist/assets/chunk-QZHKN3VN-DJRjGeIo.js +1 -0
- package/viewer/dist/assets/chunk-WU5MYG2G-C63BVvr_.js +1 -0
- package/viewer/dist/assets/{chunk-XPW4576I-BwMZI0gv.js → chunk-XPW4576I-Amo3awtq.js} +1 -1
- package/viewer/dist/assets/classDiagram-4FO5ZUOK-z_bO1V-j.js +1 -0
- package/viewer/dist/assets/classDiagram-v2-Q7XG4LA2-z_bO1V-j.js +1 -0
- package/viewer/dist/assets/{cose-bilkent-S5V4N54A-NGC7gYHM.js → cose-bilkent-S5V4N54A-CO8yESCW.js} +1 -1
- package/viewer/dist/assets/{dagre-BM42HDAG-RD63uyvd.js → dagre-BM42HDAG-BnmNVNI2.js} +1 -1
- package/viewer/dist/assets/{diagram-2AECGRRQ-hwnqqCcb.js → diagram-2AECGRRQ-lcGXcbei.js} +1 -1
- package/viewer/dist/assets/{diagram-5GNKFQAL-q8EaoZSG.js → diagram-5GNKFQAL-Cj3-lPUt.js} +1 -1
- package/viewer/dist/assets/{diagram-KO2AKTUF-D4_5Qf-l.js → diagram-KO2AKTUF-CtXdRI4M.js} +1 -1
- package/viewer/dist/assets/{diagram-LMA3HP47-D8pwekFs.js → diagram-LMA3HP47-CIyLAzX7.js} +1 -1
- package/viewer/dist/assets/{diagram-OG6HWLK6-D9KinIWZ.js → diagram-OG6HWLK6-BwF4bQCv.js} +1 -1
- package/viewer/dist/assets/{dist-CFOOgrqc.js → dist-DzXuQd4N.js} +1 -1
- package/viewer/dist/assets/{erDiagram-TEJ5UH35-D0Wfq250.js → erDiagram-TEJ5UH35-DjwFw9yq.js} +1 -1
- package/viewer/dist/assets/eventmodeling-FCH6USID-BlKFmSzA.js +1 -0
- package/viewer/dist/assets/{flowDiagram-I6XJVG4X-Y2DY-Ze2.js → flowDiagram-I6XJVG4X-CzXbf7vQ.js} +1 -1
- package/viewer/dist/assets/{ganttDiagram-6RSMTGT7-BnqkeLVw.js → ganttDiagram-6RSMTGT7-BYcIhfmm.js} +1 -1
- package/viewer/dist/assets/{gitGraph-WXDBUCRP-Cft7usRT.js → gitGraph-WXDBUCRP-H8XeJ9QB.js} +1 -1
- package/viewer/dist/assets/{gitGraphDiagram-PVQCEYII-D-cYtraK.js → gitGraphDiagram-PVQCEYII-DtAPXKFK.js} +1 -1
- package/viewer/dist/assets/index-Bqs39Itl.css +2 -0
- package/viewer/dist/assets/index-DLPCG_Or.js +98 -0
- package/viewer/dist/assets/{info-J43DQDTF-Djc8Bx3F.js → info-J43DQDTF-BQScorZ0.js} +1 -1
- package/viewer/dist/assets/{infoDiagram-5YYISTIA-D-ehtyyJ.js → infoDiagram-5YYISTIA-Udl1omvH.js} +1 -1
- package/viewer/dist/assets/{ishikawaDiagram-YF4QCWOH-Ct3f6bH-.js → ishikawaDiagram-YF4QCWOH-VnfzT_hk.js} +1 -1
- package/viewer/dist/assets/{journeyDiagram-JHISSGLW-DXlULEmi.js → journeyDiagram-JHISSGLW-Btn4EVoD.js} +1 -1
- package/viewer/dist/assets/{kanban-definition-UN3LZRKU-3vE9h-R7.js → kanban-definition-UN3LZRKU-flOzWhPe.js} +1 -1
- package/viewer/dist/assets/{line-B8MygbLB.js → line-DJJ9BLuY.js} +1 -1
- package/viewer/dist/assets/{linear-CfMuM0B3.js → linear-C2SUy5ns.js} +1 -1
- package/viewer/dist/assets/{mermaid-parser.core-DzlZTbbh.js → mermaid-parser.core-xhSeYiZo.js} +2 -2
- package/viewer/dist/assets/{mermaid.core-IM-sPiyq.js → mermaid.core-DmeSIitY.js} +3 -3
- package/viewer/dist/assets/{mindmap-definition-RKZ34NQL-CMnpAq1T.js → mindmap-definition-RKZ34NQL-CCJcMKx1.js} +1 -1
- package/viewer/dist/assets/{packet-YPE3B663-D44AzgHh.js → packet-YPE3B663-DS8RscAk.js} +1 -1
- package/viewer/dist/assets/{pie-LRSECV5Y-DL8AVJH_.js → pie-LRSECV5Y-I2ZQhrNJ.js} +1 -1
- package/viewer/dist/assets/{pieDiagram-4H26LBE5-FvKK5jd7.js → pieDiagram-4H26LBE5-BS5HMs4j.js} +1 -1
- package/viewer/dist/assets/{quadrantDiagram-W4KKPZXB-CmjSkU8c.js → quadrantDiagram-W4KKPZXB-W4H8cw2_.js} +1 -1
- package/viewer/dist/assets/{radar-GUYGQ44K-BvfZTVyH.js → radar-GUYGQ44K-kf6QvSne.js} +1 -1
- package/viewer/dist/assets/{requirementDiagram-4Y6WPE33-BOjca3VH.js → requirementDiagram-4Y6WPE33-DSbuDQGQ.js} +1 -1
- package/viewer/dist/assets/{sankeyDiagram-5OEKKPKP-ANcjfNix.js → sankeyDiagram-5OEKKPKP-CH8Qr2vL.js} +1 -1
- package/viewer/dist/assets/{sequenceDiagram-3UESZ5HK-BLQ9AL7I.js → sequenceDiagram-3UESZ5HK-EugVcdad.js} +1 -1
- package/viewer/dist/assets/src-CM_9kdrU.js +1 -0
- package/viewer/dist/assets/{stateDiagram-AJRCARHV-D6CriBS6.js → stateDiagram-AJRCARHV-DiFl94Qy.js} +1 -1
- package/viewer/dist/assets/stateDiagram-v2-BHNVJYJU-BlJV8F13.js +1 -0
- package/viewer/dist/assets/{timeline-definition-PNZ67QCA-BNhWZ_DL.js → timeline-definition-PNZ67QCA-B0KW9GUN.js} +1 -1
- package/viewer/dist/assets/{treeView-BLDUP644-CY6Ph5Pu.js → treeView-BLDUP644-CAEY4mxq.js} +1 -1
- package/viewer/dist/assets/{treemap-LRROVOQU-DChSA_Qx.js → treemap-LRROVOQU-VVaEaTlU.js} +1 -1
- package/viewer/dist/assets/{vennDiagram-CIIHVFJN-C01WznAC.js → vennDiagram-CIIHVFJN-BSLGNfJd.js} +1 -1
- package/viewer/dist/assets/{wardley-L42UT6IY-BJ8uNoJu.js → wardley-L42UT6IY-C-5cXbAU.js} +1 -1
- package/viewer/dist/assets/{wardleyDiagram-YWT4CUSO-DwDEzlVm.js → wardleyDiagram-YWT4CUSO-COk4TVnQ.js} +1 -1
- package/viewer/dist/assets/{xychartDiagram-2RQKCTM6-BCvIDwU0.js → xychartDiagram-2RQKCTM6-CClGJLJp.js} +1 -1
- package/viewer/dist/index.html +3 -3
- package/dist/mcp/git.js.map +0 -1
- package/viewer/dist/assets/architecture-7EHR7CIX-CGfWeim3.js +0 -1
- package/viewer/dist/assets/channel-19IdUS_c.js +0 -1
- package/viewer/dist/assets/chunk-LZXEDZCA-CclT9MXr.js +0 -2
- package/viewer/dist/assets/chunk-QZHKN3VN-BKc_Kg2Z.js +0 -1
- package/viewer/dist/assets/chunk-WU5MYG2G-9ssTSMzt.js +0 -1
- package/viewer/dist/assets/classDiagram-4FO5ZUOK-DXv85WFd.js +0 -1
- package/viewer/dist/assets/classDiagram-v2-Q7XG4LA2-DXv85WFd.js +0 -1
- package/viewer/dist/assets/eventmodeling-FCH6USID-D3KRSuC1.js +0 -1
- package/viewer/dist/assets/index-CDR-riG2.css +0 -2
- package/viewer/dist/assets/index-DRPsTWe2.js +0 -98
- package/viewer/dist/assets/src-CAMdANUp.js +0 -1
- package/viewer/dist/assets/stateDiagram-v2-BHNVJYJU-DcTp66RQ.js +0 -1
package/dist/core/scaffold.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/** Turn a folder slug into a human-readable project name: pyramid-server → Pyramid Server. */
|
|
2
|
+
export declare function titleCaseFromSlug(slug: string): string;
|
|
3
|
+
/** The starter plan.md body, parameterized by the project's display name. */
|
|
4
|
+
export declare function starterPlan(name: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Create constellation/ with a starter plan.md. Throws if it already exists.
|
|
7
|
+
* The project name defaults to a title-cased version of the target folder
|
|
8
|
+
* (so pyramid-server → "Pyramid Server"); pass opts.name to override it. The
|
|
9
|
+
* resolved name is returned so callers can echo / confirm it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function initPlan(targetDir: string, opts?: {
|
|
12
|
+
name?: string;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
root: string;
|
|
15
|
+
name: string;
|
|
16
|
+
}>;
|
package/dist/core/scaffold.js
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { access, mkdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/** Turn a folder slug into a human-readable project name: pyramid-server → Pyramid Server. */
|
|
4
|
+
export function titleCaseFromSlug(slug) {
|
|
5
|
+
return slug
|
|
6
|
+
.replace(/[-_]+/g, ' ') // kebab / snake → spaces
|
|
7
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2') // split camelCase
|
|
8
|
+
.trim()
|
|
9
|
+
.split(/\s+/)
|
|
10
|
+
.filter(Boolean)
|
|
11
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
12
|
+
.join(' ');
|
|
13
|
+
}
|
|
14
|
+
/** The starter plan.md body, parameterized by the project's display name. */
|
|
15
|
+
export function starterPlan(name) {
|
|
16
|
+
return `---
|
|
17
|
+
name: ${name}
|
|
5
18
|
---
|
|
6
19
|
|
|
7
20
|
# Project Plan
|
|
@@ -18,9 +31,19 @@ name: Project plan
|
|
|
18
31
|
|
|
19
32
|
Code has not been reconciled against this plan yet.
|
|
20
33
|
`;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create constellation/ with a starter plan.md. Throws if it already exists.
|
|
37
|
+
* The project name defaults to a title-cased version of the target folder
|
|
38
|
+
* (so pyramid-server → "Pyramid Server"); pass opts.name to override it. The
|
|
39
|
+
* resolved name is returned so callers can echo / confirm it.
|
|
40
|
+
*/
|
|
41
|
+
export async function initPlan(targetDir, opts = {}) {
|
|
42
|
+
const resolvedTarget = path.resolve(targetDir);
|
|
43
|
+
const root = path.join(resolvedTarget, 'constellation');
|
|
44
|
+
const name = opts.name?.trim() ||
|
|
45
|
+
titleCaseFromSlug(path.basename(resolvedTarget)) ||
|
|
46
|
+
'Project plan';
|
|
24
47
|
try {
|
|
25
48
|
await access(root);
|
|
26
49
|
throw new Error(`${root} already exists`);
|
|
@@ -30,7 +53,7 @@ export async function initPlan(targetDir) {
|
|
|
30
53
|
throw err;
|
|
31
54
|
}
|
|
32
55
|
await mkdir(root, { recursive: true });
|
|
33
|
-
await writeFile(path.join(root, 'plan.md'),
|
|
34
|
-
return root;
|
|
56
|
+
await writeFile(path.join(root, 'plan.md'), starterPlan(name), { flag: 'wx' });
|
|
57
|
+
return { root, name };
|
|
35
58
|
}
|
|
36
59
|
//# sourceMappingURL=scaffold.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/core/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/core/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,8FAA8F;AAC9F,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI;SACR,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,yBAAyB;SAChD,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,kBAAkB;SACzD,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO;QACD,IAAI;;;;;;;;;;;;;;;;CAgBX,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,OAA0B,EAAE;IAE5B,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IACxD,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE;QACjB,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAChD,cAAc,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAAE,MAAM,GAAG,CAAC;IAChF,CAAC;IACD,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type SyncActivity, type SyncPoint } from './git.js';
|
|
2
|
+
export type SyncState = 'in-sync' | 'drifted' | 'dirty' | 'never-synced' | 'no-git';
|
|
3
|
+
export interface SyncStatus {
|
|
4
|
+
state: SyncState;
|
|
5
|
+
marker: SyncPoint | null;
|
|
6
|
+
plan_dirty: boolean;
|
|
7
|
+
plan_changes_since_marker: number;
|
|
8
|
+
code_commits_since_marker: number;
|
|
9
|
+
integrity: {
|
|
10
|
+
errors: number;
|
|
11
|
+
warnings: number;
|
|
12
|
+
orphans: number;
|
|
13
|
+
};
|
|
14
|
+
status_rollup: Record<string, number>;
|
|
15
|
+
total_cards: number;
|
|
16
|
+
activity: SyncActivity[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The plan's freshness/trust state, computed live from git + lint on every call —
|
|
20
|
+
* never stored, so it cannot go stale or lie. Composes the sync marker
|
|
21
|
+
* (.sync.json), working-tree state, drift since the marker, lint integrity, the
|
|
22
|
+
* card-status rollup, and recent plan activity into one glanceable verdict. When
|
|
23
|
+
* the plan isn't in a git repo, returns `state: 'no-git'` (the viewer hides the
|
|
24
|
+
* freshness pill) but still reports the git-independent lint + rollup.
|
|
25
|
+
*/
|
|
26
|
+
export declare function computeSyncStatus(planRoot: string, options?: {
|
|
27
|
+
activityLimit?: number;
|
|
28
|
+
}): Promise<SyncStatus>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { countCodeCommitsSince, diffPlan, planDirty, readSyncPoint, recentPlanActivity, } from './git.js';
|
|
2
|
+
import { lintPlan } from './lint.js';
|
|
3
|
+
const STATUS_KEYS = ['planned', 'building', 'built', 'verified'];
|
|
4
|
+
/**
|
|
5
|
+
* The plan's freshness/trust state, computed live from git + lint on every call —
|
|
6
|
+
* never stored, so it cannot go stale or lie. Composes the sync marker
|
|
7
|
+
* (.sync.json), working-tree state, drift since the marker, lint integrity, the
|
|
8
|
+
* card-status rollup, and recent plan activity into one glanceable verdict. When
|
|
9
|
+
* the plan isn't in a git repo, returns `state: 'no-git'` (the viewer hides the
|
|
10
|
+
* freshness pill) but still reports the git-independent lint + rollup.
|
|
11
|
+
*/
|
|
12
|
+
export async function computeSyncStatus(planRoot, options = {}) {
|
|
13
|
+
const lint = await lintPlan(planRoot);
|
|
14
|
+
const orphans = [...lint.index.cards.keys()].filter((h) => (lint.index.connectedHandles.get(h)?.size ?? 0) === 0);
|
|
15
|
+
const status_rollup = { none: 0 };
|
|
16
|
+
for (const key of STATUS_KEYS)
|
|
17
|
+
status_rollup[key] = 0;
|
|
18
|
+
for (const card of lint.index.cards.values()) {
|
|
19
|
+
const key = card.status ?? 'none';
|
|
20
|
+
status_rollup[key] = (status_rollup[key] ?? 0) + 1;
|
|
21
|
+
}
|
|
22
|
+
const base = {
|
|
23
|
+
integrity: {
|
|
24
|
+
errors: lint.errors.length,
|
|
25
|
+
warnings: lint.warnings.length,
|
|
26
|
+
orphans: orphans.length,
|
|
27
|
+
},
|
|
28
|
+
status_rollup,
|
|
29
|
+
total_cards: lint.index.cards.size,
|
|
30
|
+
};
|
|
31
|
+
let marker = null;
|
|
32
|
+
let plan_dirty = false;
|
|
33
|
+
let plan_changes_since_marker = 0;
|
|
34
|
+
let code_commits_since_marker = 0;
|
|
35
|
+
let activity = [];
|
|
36
|
+
try {
|
|
37
|
+
marker = await readSyncPoint(planRoot);
|
|
38
|
+
plan_dirty = await planDirty(planRoot);
|
|
39
|
+
activity = await recentPlanActivity(planRoot, options.activityLimit ?? 6);
|
|
40
|
+
if (marker) {
|
|
41
|
+
try {
|
|
42
|
+
const diff = await diffPlan(planRoot, marker.synced_sha, 'HEAD');
|
|
43
|
+
plan_changes_since_marker = diff.changes.length;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// marker sha unreachable (e.g. rebased history) — leave 0
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
code_commits_since_marker = await countCodeCommitsSince(planRoot, marker.synced_sha);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// ignore — drift count is best-effort
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// repoRootFor threw → not a git repo; no freshness signal is available.
|
|
58
|
+
return {
|
|
59
|
+
state: 'no-git',
|
|
60
|
+
marker: null,
|
|
61
|
+
plan_dirty: false,
|
|
62
|
+
plan_changes_since_marker: 0,
|
|
63
|
+
code_commits_since_marker: 0,
|
|
64
|
+
activity: [],
|
|
65
|
+
...base,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const state = !marker
|
|
69
|
+
? 'never-synced'
|
|
70
|
+
: plan_changes_since_marker > 0 || code_commits_since_marker > 0
|
|
71
|
+
? 'drifted'
|
|
72
|
+
: plan_dirty
|
|
73
|
+
? 'dirty'
|
|
74
|
+
: 'in-sync';
|
|
75
|
+
return {
|
|
76
|
+
state,
|
|
77
|
+
marker,
|
|
78
|
+
plan_dirty,
|
|
79
|
+
plan_changes_since_marker,
|
|
80
|
+
code_commits_since_marker,
|
|
81
|
+
activity,
|
|
82
|
+
...base,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -29,6 +29,18 @@ export interface Connection {
|
|
|
29
29
|
a: string;
|
|
30
30
|
b: string;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* A sibling repo declared in PLAN-PROJECT `connected_repos`. A repo-level link
|
|
34
|
+
* only — never a card connection. The path is local topology (relative to the
|
|
35
|
+
* repo root, or absolute) and is never validated by lint.
|
|
36
|
+
*/
|
|
37
|
+
export interface ConnectedRepo {
|
|
38
|
+
/** Lowercase id used as the `repo` selector. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** Path to the connected repo's root, relative to this repo's root (or absolute). */
|
|
41
|
+
path: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
}
|
|
32
44
|
export type Severity = 'error' | 'warning';
|
|
33
45
|
export interface Issue {
|
|
34
46
|
severity: Severity;
|