dxcomplete 0.1.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.
Files changed (121) hide show
  1. package/.env.example +11 -0
  2. package/README.md +215 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +212 -0
  5. package/dist/http/server.d.ts +7 -0
  6. package/dist/http/server.js +236 -0
  7. package/dist/http/service.d.ts +7 -0
  8. package/dist/http/service.js +725 -0
  9. package/dist/init.d.ts +13 -0
  10. package/dist/init.js +128 -0
  11. package/dist/install-manifest.d.ts +25 -0
  12. package/dist/install-manifest.js +96 -0
  13. package/dist/mcp/docs.d.ts +98 -0
  14. package/dist/mcp/docs.js +438 -0
  15. package/dist/mcp/server.d.ts +20 -0
  16. package/dist/mcp/server.js +2345 -0
  17. package/dist/package-root.d.ts +2 -0
  18. package/dist/package-root.js +28 -0
  19. package/dist/runtime/actor.d.ts +14 -0
  20. package/dist/runtime/actor.js +42 -0
  21. package/dist/runtime/auth.d.ts +162 -0
  22. package/dist/runtime/auth.js +394 -0
  23. package/dist/runtime/check.d.ts +7 -0
  24. package/dist/runtime/check.js +16 -0
  25. package/dist/runtime/config.d.ts +17 -0
  26. package/dist/runtime/config.js +93 -0
  27. package/dist/runtime/mongo.d.ts +9 -0
  28. package/dist/runtime/mongo.js +56 -0
  29. package/dist/runtime/records.d.ts +336 -0
  30. package/dist/runtime/records.js +1463 -0
  31. package/dist/runtime/workspace.d.ts +19 -0
  32. package/dist/runtime/workspace.js +102 -0
  33. package/dist/upgrade.d.ts +20 -0
  34. package/dist/upgrade.js +246 -0
  35. package/dist/validate.d.ts +10 -0
  36. package/dist/validate.js +119 -0
  37. package/dist/version.d.ts +3 -0
  38. package/dist/version.js +12 -0
  39. package/docs/codex-integration.md +29 -0
  40. package/docs/cost-model.md +61 -0
  41. package/docs/decision-basis.md +57 -0
  42. package/docs/diagrams.md +31 -0
  43. package/docs/glossary.md +147 -0
  44. package/docs/index.md +60 -0
  45. package/docs/model.md +110 -0
  46. package/docs/open-questions.md +61 -0
  47. package/docs/roles.md +42 -0
  48. package/docs/taxonomy.md +96 -0
  49. package/docs/workflows.md +60 -0
  50. package/package.json +62 -0
  51. package/scripts/check-env-surface.mjs +136 -0
  52. package/scripts/check-public-copy.mjs +263 -0
  53. package/scripts/check-service-boundary.mjs +63 -0
  54. package/scripts/dogfood-work-order.mjs +506 -0
  55. package/scripts/smoke-mcp-http.mjs +3572 -0
  56. package/src/cli.ts +268 -0
  57. package/src/http/server.ts +314 -0
  58. package/src/http/service.ts +934 -0
  59. package/src/init.ts +227 -0
  60. package/src/install-manifest.ts +144 -0
  61. package/src/mcp/docs.ts +557 -0
  62. package/src/mcp/server.ts +3525 -0
  63. package/src/package-root.ts +31 -0
  64. package/src/runtime/actor.ts +61 -0
  65. package/src/runtime/auth.ts +673 -0
  66. package/src/runtime/check.ts +18 -0
  67. package/src/runtime/config.ts +128 -0
  68. package/src/runtime/mongo.ts +89 -0
  69. package/src/runtime/records.ts +2303 -0
  70. package/src/runtime/workspace.ts +155 -0
  71. package/src/upgrade.ts +356 -0
  72. package/src/validate.ts +139 -0
  73. package/src/version.ts +16 -0
  74. package/templates/github/workflows/dxcomplete.yml +16 -0
  75. package/templates/next/pages/api/auth/callback/google.js +12 -0
  76. package/templates/next/pages/api/dxcomplete/[...path].js +12 -0
  77. package/templates/next/pages/api/dxcomplete.js +12 -0
  78. package/templates/next/pages/api/mcp.js +12 -0
  79. package/templates/next/vercel.json +18 -0
  80. package/templates/process/README.md +38 -0
  81. package/templates/process/controls.yml +113 -0
  82. package/templates/process/cost-model.yml +71 -0
  83. package/templates/process/decision-basis.yml +53 -0
  84. package/templates/process/decisions/.gitkeep +1 -0
  85. package/templates/process/diagrams/00-decision-basis.mmd +24 -0
  86. package/templates/process/diagrams/00-overview.mmd +20 -0
  87. package/templates/process/diagrams/01-intake-triage.mmd +20 -0
  88. package/templates/process/diagrams/02-product-definition.mmd +14 -0
  89. package/templates/process/diagrams/03-engineering-execution.mmd +15 -0
  90. package/templates/process/diagrams/04-qa-verification.mmd +12 -0
  91. package/templates/process/diagrams/05-product-validation.mmd +12 -0
  92. package/templates/process/diagrams/06-change-release-control.mmd +16 -0
  93. package/templates/process/diagrams/07-deployment-operations.mmd +16 -0
  94. package/templates/process/diagrams/08-support-incident-management.mmd +16 -0
  95. package/templates/process/diagrams/09-problem-improvement.mmd +14 -0
  96. package/templates/process/diagrams/10-risk-control-management.mmd +14 -0
  97. package/templates/process/diagrams/11-audit-evidence-capture.mmd +13 -0
  98. package/templates/process/evidence/.gitkeep +1 -0
  99. package/templates/process/risks/.gitkeep +1 -0
  100. package/templates/process/roles.yml +96 -0
  101. package/templates/process/taxonomy.yml +514 -0
  102. package/templates/process/workflows.yml +210 -0
  103. package/website/.well-known/oauth-authorization-server +22 -0
  104. package/website/.well-known/oauth-protected-resource/api/dxcomplete/mcp +10 -0
  105. package/website/.well-known/oauth-protected-resource/api/mcp +10 -0
  106. package/website/README.md +12 -0
  107. package/website/app.js +36 -0
  108. package/website/flow.html +85 -0
  109. package/website/glossary.html +280 -0
  110. package/website/index.html +90 -0
  111. package/website/objects.html +287 -0
  112. package/website/outcomes.html +117 -0
  113. package/website/phase-build.html +101 -0
  114. package/website/phase-elicit.html +102 -0
  115. package/website/phase-go-live.html +103 -0
  116. package/website/phase-measure.html +93 -0
  117. package/website/phase-operate.html +102 -0
  118. package/website/phase-orient.html +92 -0
  119. package/website/phase-weigh.html +98 -0
  120. package/website/roles.html +52 -0
  121. package/website/styles.css +1169 -0
package/dist/init.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export type InitOptions = {
2
+ targetDir: string;
3
+ force?: boolean;
4
+ dryRun?: boolean;
5
+ includeGithubWorkflow?: boolean;
6
+ };
7
+ export type InitResult = {
8
+ targetDir: string;
9
+ written: string[];
10
+ skipped: string[];
11
+ planned: string[];
12
+ };
13
+ export declare function initProject(options: InitOptions): Promise<InitResult>;
package/dist/init.js ADDED
@@ -0,0 +1,128 @@
1
+ import { copyFile, mkdir, readdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { INSTALL_MANIFEST_PATH, writeInstallManifest } from "./install-manifest.js";
4
+ import { fileExists, resolvePackageRoot } from "./package-root.js";
5
+ import { getUpgradeManagedFiles } from "./upgrade.js";
6
+ export async function initProject(options) {
7
+ const targetDir = path.resolve(options.targetDir);
8
+ const force = options.force ?? false;
9
+ const dryRun = options.dryRun ?? false;
10
+ const includeGithubWorkflow = options.includeGithubWorkflow ?? true;
11
+ const packageRoot = await resolvePackageRoot();
12
+ const result = {
13
+ targetDir,
14
+ written: [],
15
+ skipped: [],
16
+ planned: []
17
+ };
18
+ await copyDirectory(path.join(packageRoot, "docs"), path.join(targetDir, "dxcomplete", "docs"), { force, dryRun }, result);
19
+ await copyDirectory(path.join(packageRoot, "templates", "process"), path.join(targetDir, "dxcomplete", "process"), { force, dryRun }, result);
20
+ await writeWorkspaceConfig(targetDir, { force, dryRun }, result);
21
+ await copyDirectory(path.join(packageRoot, "templates", "next", "pages"), path.join(targetDir, "pages"), { force, dryRun }, result);
22
+ await copyFileIfAvailable(path.join(packageRoot, "templates", "next", "vercel.json"), path.join(targetDir, "vercel.json"), { force, dryRun }, result);
23
+ if (includeGithubWorkflow) {
24
+ await copyDirectory(path.join(packageRoot, "templates", "github", "workflows"), path.join(targetDir, ".github", "workflows"), { force, dryRun }, result);
25
+ }
26
+ await writeScaffoldManifest(packageRoot, targetDir, { force, dryRun }, result);
27
+ return result;
28
+ }
29
+ async function writeScaffoldManifest(packageRoot, targetDir, options, result) {
30
+ const managedFiles = getUpgradeManagedFiles(packageRoot, targetDir);
31
+ const managedDestinations = new Set(managedFiles.map((file) => file.destinationRelative));
32
+ const skippedManagedFile = result.skipped.some((file) => managedDestinations.has(file));
33
+ if (skippedManagedFile && !options.force) {
34
+ result.skipped.push(INSTALL_MANIFEST_PATH);
35
+ return;
36
+ }
37
+ if (options.dryRun) {
38
+ result.planned.push(INSTALL_MANIFEST_PATH);
39
+ return;
40
+ }
41
+ await writeInstallManifest(targetDir, managedFiles);
42
+ result.written.push(INSTALL_MANIFEST_PATH);
43
+ }
44
+ async function copyFileIfAvailable(sourcePath, destinationPath, options, result) {
45
+ if (!(await fileExists(sourcePath))) {
46
+ return;
47
+ }
48
+ const relativeDestination = path.relative(result.targetDir, destinationPath);
49
+ const exists = await fileExists(destinationPath);
50
+ if (exists && !options.force) {
51
+ result.skipped.push(relativeDestination);
52
+ return;
53
+ }
54
+ if (options.dryRun) {
55
+ result.planned.push(relativeDestination);
56
+ return;
57
+ }
58
+ await mkdir(path.dirname(destinationPath), { recursive: true });
59
+ await copyFile(sourcePath, destinationPath);
60
+ result.written.push(relativeDestination);
61
+ }
62
+ async function writeWorkspaceConfig(targetDir, options, result) {
63
+ const destinationPath = path.join(targetDir, "dxcomplete", "workspace.json");
64
+ const relativeDestination = path.relative(result.targetDir, destinationPath);
65
+ const exists = await fileExists(destinationPath);
66
+ if (exists && !options.force) {
67
+ result.skipped.push(relativeDestination);
68
+ return;
69
+ }
70
+ if (options.dryRun) {
71
+ result.planned.push(relativeDestination);
72
+ return;
73
+ }
74
+ const workspaceId = slugifyWorkspaceId(path.basename(targetDir)) || "dxcomplete-workspace";
75
+ const workspaceName = titleizeWorkspaceName(path.basename(targetDir)) || "DX Complete Workspace";
76
+ const content = `${JSON.stringify({
77
+ workspaceId,
78
+ name: workspaceName,
79
+ bootstrapMembers: []
80
+ }, null, 2)}\n`;
81
+ await mkdir(path.dirname(destinationPath), { recursive: true });
82
+ await writeFile(destinationPath, content, "utf8");
83
+ result.written.push(relativeDestination);
84
+ }
85
+ async function copyDirectory(sourceDir, destinationDir, options, result) {
86
+ const entries = await readdir(sourceDir, { withFileTypes: true });
87
+ if (!options.dryRun) {
88
+ await mkdir(destinationDir, { recursive: true });
89
+ }
90
+ for (const entry of entries) {
91
+ const sourcePath = path.join(sourceDir, entry.name);
92
+ const destinationPath = path.join(destinationDir, entry.name);
93
+ if (entry.isDirectory()) {
94
+ await copyDirectory(sourcePath, destinationPath, options, result);
95
+ continue;
96
+ }
97
+ if (!entry.isFile()) {
98
+ continue;
99
+ }
100
+ const relativeDestination = path.relative(result.targetDir, destinationPath);
101
+ const exists = await fileExists(destinationPath);
102
+ if (exists && !options.force) {
103
+ result.skipped.push(relativeDestination);
104
+ continue;
105
+ }
106
+ if (options.dryRun) {
107
+ result.planned.push(relativeDestination);
108
+ continue;
109
+ }
110
+ await mkdir(path.dirname(destinationPath), { recursive: true });
111
+ await copyFile(sourcePath, destinationPath);
112
+ result.written.push(relativeDestination);
113
+ }
114
+ }
115
+ function slugifyWorkspaceId(value) {
116
+ return value
117
+ .trim()
118
+ .toLowerCase()
119
+ .replace(/[^a-z0-9]+/g, "-")
120
+ .replace(/^-+|-+$/g, "");
121
+ }
122
+ function titleizeWorkspaceName(value) {
123
+ return value
124
+ .trim()
125
+ .replace(/[-_]+/g, " ")
126
+ .replace(/\s+/g, " ")
127
+ .replace(/\b\w/g, (letter) => letter.toUpperCase());
128
+ }
@@ -0,0 +1,25 @@
1
+ export declare const INSTALL_MANIFEST_PATH: string;
2
+ export declare const INSTALL_MANIFEST_SCHEMA_VERSION = 1;
3
+ export type UpgradeManagedFile = {
4
+ destinationRelative: string;
5
+ sourceRelative: string;
6
+ sourcePath: string;
7
+ destinationPath: string;
8
+ strategy: "copy" | "merge-vercel";
9
+ };
10
+ export type InstallManifest = {
11
+ schemaVersion: number;
12
+ packageVersion: string;
13
+ workspaceCompatibility: number;
14
+ installedAt: string;
15
+ managedFiles: Record<string, InstallManifestFile>;
16
+ };
17
+ export type InstallManifestFile = {
18
+ sha256: string;
19
+ source: string;
20
+ strategy: UpgradeManagedFile["strategy"];
21
+ };
22
+ export declare function readInstallManifest(targetDir: string): Promise<InstallManifest | undefined>;
23
+ export declare function writeInstallManifest(targetDir: string, files: UpgradeManagedFile[]): Promise<void>;
24
+ export declare function hashFile(filePath: string): Promise<string>;
25
+ export declare function hashContent(content: string | Buffer): string;
@@ -0,0 +1,96 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileExists } from "./package-root.js";
5
+ import { DXCOMPLETE_PACKAGE_VERSION, WORKSPACE_COMPATIBILITY_VERSION } from "./version.js";
6
+ export const INSTALL_MANIFEST_PATH = path.join("dxcomplete", ".install-manifest.json");
7
+ export const INSTALL_MANIFEST_SCHEMA_VERSION = 1;
8
+ export async function readInstallManifest(targetDir) {
9
+ const manifestPath = path.join(targetDir, INSTALL_MANIFEST_PATH);
10
+ if (!(await fileExists(manifestPath))) {
11
+ return undefined;
12
+ }
13
+ const parsed = JSON.parse(await readFile(manifestPath, "utf8"));
14
+ return parseInstallManifest(parsed, manifestPath);
15
+ }
16
+ export async function writeInstallManifest(targetDir, files) {
17
+ const managedFiles = {};
18
+ for (const file of files) {
19
+ if (!(await fileExists(file.destinationPath))) {
20
+ continue;
21
+ }
22
+ managedFiles[file.destinationRelative] = {
23
+ sha256: await hashFile(file.destinationPath),
24
+ source: file.sourceRelative,
25
+ strategy: file.strategy
26
+ };
27
+ }
28
+ const manifest = {
29
+ schemaVersion: INSTALL_MANIFEST_SCHEMA_VERSION,
30
+ packageVersion: DXCOMPLETE_PACKAGE_VERSION,
31
+ workspaceCompatibility: WORKSPACE_COMPATIBILITY_VERSION,
32
+ installedAt: new Date().toISOString(),
33
+ managedFiles
34
+ };
35
+ const manifestPath = path.join(targetDir, INSTALL_MANIFEST_PATH);
36
+ await mkdir(path.dirname(manifestPath), { recursive: true });
37
+ await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
38
+ }
39
+ export async function hashFile(filePath) {
40
+ return hashContent(await readFile(filePath));
41
+ }
42
+ export function hashContent(content) {
43
+ return createHash("sha256").update(content).digest("hex");
44
+ }
45
+ function parseInstallManifest(value, source) {
46
+ if (!value || typeof value !== "object") {
47
+ throw new Error(`${source} must be a JSON object.`);
48
+ }
49
+ const input = value;
50
+ const schemaVersion = readNumber(input.schemaVersion, "schemaVersion", source);
51
+ const packageVersion = readString(input.packageVersion, "packageVersion", source);
52
+ const workspaceCompatibility = readNumber(input.workspaceCompatibility, "workspaceCompatibility", source);
53
+ const installedAt = readString(input.installedAt, "installedAt", source);
54
+ const managedFiles = parseManagedFiles(input.managedFiles, source);
55
+ return {
56
+ schemaVersion,
57
+ packageVersion,
58
+ workspaceCompatibility,
59
+ installedAt,
60
+ managedFiles
61
+ };
62
+ }
63
+ function parseManagedFiles(value, source) {
64
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
65
+ throw new Error(`${source} managedFiles must be a JSON object.`);
66
+ }
67
+ const output = {};
68
+ for (const [filePath, fileValue] of Object.entries(value)) {
69
+ if (!fileValue || typeof fileValue !== "object" || Array.isArray(fileValue)) {
70
+ throw new Error(`${source} managedFiles.${filePath} must be a JSON object.`);
71
+ }
72
+ const file = fileValue;
73
+ const strategy = readString(file.strategy, `managedFiles.${filePath}.strategy`, source);
74
+ if (strategy !== "copy" && strategy !== "merge-vercel") {
75
+ throw new Error(`${source} managedFiles.${filePath}.strategy must be copy or merge-vercel.`);
76
+ }
77
+ output[filePath] = {
78
+ sha256: readString(file.sha256, `managedFiles.${filePath}.sha256`, source),
79
+ source: readString(file.source, `managedFiles.${filePath}.source`, source),
80
+ strategy
81
+ };
82
+ }
83
+ return output;
84
+ }
85
+ function readString(value, key, source) {
86
+ if (typeof value !== "string" || !value.trim()) {
87
+ throw new Error(`${source} ${key} must be a non-empty string.`);
88
+ }
89
+ return value;
90
+ }
91
+ function readNumber(value, key, source) {
92
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
93
+ throw new Error(`${source} ${key} must be a non-negative integer.`);
94
+ }
95
+ return value;
96
+ }
@@ -0,0 +1,98 @@
1
+ export declare const DOC_SOURCE_BASE_URL = "https://dxcomplete.directeddomains.com";
2
+ export declare const DOC_PAGE_IDS: readonly ["start_here", "outcomes", "flow", "records", "roles", "glossary"];
3
+ export type DocPageId = (typeof DOC_PAGE_IDS)[number];
4
+ type BaseDocPage = {
5
+ page: DocPageId;
6
+ title: string;
7
+ sourceUrl: string;
8
+ summary: string;
9
+ };
10
+ type StartHereDoc = BaseDocPage & {
11
+ page: "start_here";
12
+ phases: Array<{
13
+ number: string;
14
+ name: string;
15
+ description: string;
16
+ }>;
17
+ };
18
+ type OutcomesDoc = BaseDocPage & {
19
+ page: "outcomes";
20
+ outcomes: Array<{
21
+ name: string;
22
+ description: string;
23
+ }>;
24
+ transformationValue: Array<{
25
+ state: string;
26
+ focus: string;
27
+ description: string;
28
+ }>;
29
+ goodLooksLike: Array<{
30
+ statement: string;
31
+ description: string;
32
+ }>;
33
+ };
34
+ type FlowDoc = BaseDocPage & {
35
+ page: "flow";
36
+ phases: Array<{
37
+ number: string;
38
+ name: string;
39
+ description: string;
40
+ sourceUrl: string;
41
+ }>;
42
+ };
43
+ type RecordsDoc = BaseDocPage & {
44
+ page: "records";
45
+ routingGuidance: {
46
+ principle: string;
47
+ sharpTest: string;
48
+ axes: Array<{
49
+ name: string;
50
+ test: string;
51
+ }>;
52
+ routingOrder: Array<{
53
+ signal: string;
54
+ record: string;
55
+ }>;
56
+ edgeCases: string[];
57
+ promotion: string;
58
+ futureContainers: Array<{
59
+ name: string;
60
+ status: string;
61
+ use: string;
62
+ }>;
63
+ };
64
+ groups: Array<{
65
+ group: string;
66
+ purpose: string;
67
+ records: Array<{
68
+ name: string;
69
+ summary: string;
70
+ }>;
71
+ }>;
72
+ concepts: Array<{
73
+ name: string;
74
+ summary: string;
75
+ }>;
76
+ };
77
+ type RolesDoc = BaseDocPage & {
78
+ page: "roles";
79
+ roles: Array<{
80
+ name: string;
81
+ responsibility: string;
82
+ }>;
83
+ };
84
+ export type GlossaryTerm = {
85
+ term: string;
86
+ category: string;
87
+ definition: string;
88
+ };
89
+ type GlossaryDoc = BaseDocPage & {
90
+ page: "glossary";
91
+ terms: GlossaryTerm[];
92
+ };
93
+ export type DocPage = StartHereDoc | OutcomesDoc | FlowDoc | RecordsDoc | RolesDoc | GlossaryDoc;
94
+ export declare const DOC_REFERENCE: Record<DocPageId, DocPage>;
95
+ export declare function getDocReference(page: DocPageId, term?: string): DocPage | (BaseDocPage & {
96
+ term: GlossaryTerm;
97
+ });
98
+ export {};