oh-my-pm 1.0.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/agent-blueprints/ada-blueprint.md +69 -0
  4. package/agent-blueprints/davinci-blueprint.md +67 -0
  5. package/agent-blueprints/hammurabi-blueprint.md +69 -0
  6. package/agent-blueprints/jc-blueprint.md +67 -0
  7. package/agent-blueprints/suntzu-blueprint.md +65 -0
  8. package/dist/agents.d.ts +11 -0
  9. package/dist/agents.d.ts.map +1 -0
  10. package/dist/agents.js +138 -0
  11. package/dist/agents.js.map +1 -0
  12. package/dist/cli.d.ts +3 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +57 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/config.d.ts +28 -0
  17. package/dist/config.d.ts.map +1 -0
  18. package/dist/config.js +75 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/generator.d.ts +20 -0
  21. package/dist/generator.d.ts.map +1 -0
  22. package/dist/generator.js +119 -0
  23. package/dist/generator.js.map +1 -0
  24. package/dist/index.d.ts +11 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +20 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/install.d.ts +16 -0
  29. package/dist/install.d.ts.map +1 -0
  30. package/dist/install.js +207 -0
  31. package/dist/install.js.map +1 -0
  32. package/dist/utils/manifest.d.ts +60 -0
  33. package/dist/utils/manifest.d.ts.map +1 -0
  34. package/dist/utils/manifest.js +65 -0
  35. package/dist/utils/manifest.js.map +1 -0
  36. package/dist/utils/validation.d.ts +14 -0
  37. package/dist/utils/validation.d.ts.map +1 -0
  38. package/dist/utils/validation.js +137 -0
  39. package/dist/utils/validation.js.map +1 -0
  40. package/docs/architecture.md +54 -0
  41. package/docs/dev-harness-bridge.md +46 -0
  42. package/docs/examples/example-manifest.json +51 -0
  43. package/docs/examples/example-prd.md +47 -0
  44. package/docs/installation.md +75 -0
  45. package/docs/lifecycle.md +27 -0
  46. package/oh-my-pm.schema.json +32 -0
  47. package/package.json +55 -0
  48. package/pm-manifest.schema.json +96 -0
  49. package/src/templates/claude/CLAUDE.md +99 -0
  50. package/src/templates/generic/AGENTS.md +56 -0
  51. package/src/templates/openai/agents.py +123 -0
  52. package/src/templates/opencode/AGENTS.md +38 -0
  53. package/src/templates/opencode/oh-my-pm.json +20 -0
  54. package/src/templates/opencode/opencode.jsonc +30 -0
  55. package/src/templates/opencode/skills/ada/SKILL.md +57 -0
  56. package/src/templates/opencode/skills/davinci/SKILL.md +57 -0
  57. package/src/templates/opencode/skills/hammurabi/SKILL.md +57 -0
  58. package/src/templates/opencode/skills/jc/SKILL.md +57 -0
  59. package/src/templates/opencode/skills/oh-my-pm/SKILL.md +52 -0
  60. package/src/templates/opencode/skills/suntzu/SKILL.md +57 -0
@@ -0,0 +1,60 @@
1
+ export declare const MANIFEST_RELATIVE_PATH = ".parkops/pm_manifest.json";
2
+ export declare const MANIFEST_SCHEMA_RELATIVE_PATH = ".parkops/schemas/pm-manifest-schema.json";
3
+ export declare const MANIFEST_STATUSES: readonly ["discovery", "designed", "approved", "in_development", "blocked", "completed"];
4
+ export declare const TASK_STATUSES: readonly ["pending", "in_progress", "blocked", "completed"];
5
+ export type ManifestStatus = (typeof MANIFEST_STATUSES)[number];
6
+ export type TaskStatus = (typeof TASK_STATUSES)[number];
7
+ export type ManifestTask = {
8
+ readonly id: string;
9
+ readonly depends_on: readonly string[];
10
+ readonly spec_reference: string;
11
+ readonly description: string;
12
+ readonly status: TaskStatus;
13
+ readonly verification_criteria: readonly string[];
14
+ readonly assigned_to: string;
15
+ };
16
+ export type Manifest = {
17
+ readonly $schema: string;
18
+ readonly project_metadata: {
19
+ readonly name: string;
20
+ readonly blueprint_version: string;
21
+ readonly status: ManifestStatus;
22
+ readonly generated_by: string;
23
+ readonly generated_at: string;
24
+ };
25
+ readonly product_blueprints: {
26
+ readonly prd: string;
27
+ readonly trd: string;
28
+ readonly db_schema: string;
29
+ readonly ui_flows: readonly string[];
30
+ readonly execution_plan: string;
31
+ };
32
+ readonly execution_dag: {
33
+ readonly version: string;
34
+ readonly tasks: readonly ManifestTask[];
35
+ };
36
+ readonly feedback_channel: {
37
+ readonly blockers: readonly Blocker[];
38
+ readonly decisions: readonly Decision[];
39
+ };
40
+ };
41
+ export type Blocker = {
42
+ readonly id: string;
43
+ readonly raised_by: "dev-harness" | "oh-my-pm";
44
+ readonly description: string;
45
+ readonly proposed_solutions: readonly string[];
46
+ readonly status: "open" | "resolved";
47
+ readonly resolution: string;
48
+ };
49
+ export type Decision = {
50
+ readonly id: string;
51
+ readonly description: string;
52
+ readonly rationale: string;
53
+ readonly alternatives_considered: readonly string[];
54
+ };
55
+ export declare function buildInitialManifest(projectName: string, generatedAt: string): Manifest;
56
+ export declare function writeManifest(projectRoot: string, manifest: Manifest): Promise<string>;
57
+ export declare function readManifest(projectRoot: string): Promise<unknown>;
58
+ export declare function manifestExists(projectRoot: string): Promise<boolean>;
59
+ export declare function withStatus(manifest: Manifest, status: ManifestStatus): Manifest;
60
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ export const MANIFEST_RELATIVE_PATH = ".parkops/pm_manifest.json";
4
+ export const MANIFEST_SCHEMA_RELATIVE_PATH = ".parkops/schemas/pm-manifest-schema.json";
5
+ export const MANIFEST_STATUSES = [
6
+ "discovery",
7
+ "designed",
8
+ "approved",
9
+ "in_development",
10
+ "blocked",
11
+ "completed",
12
+ ];
13
+ export const TASK_STATUSES = ["pending", "in_progress", "blocked", "completed"];
14
+ export function buildInitialManifest(projectName, generatedAt) {
15
+ return {
16
+ $schema: "./schemas/pm-manifest-schema.json",
17
+ project_metadata: {
18
+ name: projectName,
19
+ blueprint_version: "1.0.0",
20
+ status: "discovery",
21
+ generated_by: "oh-my-pm v1.0.0",
22
+ generated_at: generatedAt,
23
+ },
24
+ product_blueprints: {
25
+ prd: "docs/prd.md",
26
+ trd: "docs/trd.md",
27
+ db_schema: "docs/db-schema.md",
28
+ ui_flows: ["docs/flows/main-flow.md"],
29
+ execution_plan: "docs/execution-plan.md",
30
+ },
31
+ execution_dag: { version: "1.0.0", tasks: [] },
32
+ feedback_channel: { blockers: [], decisions: [] },
33
+ };
34
+ }
35
+ export async function writeManifest(projectRoot, manifest) {
36
+ const manifestPath = path.join(projectRoot, MANIFEST_RELATIVE_PATH);
37
+ await fs.ensureDir(path.dirname(manifestPath));
38
+ await fs.writeJson(manifestPath, manifest, { spaces: 2 });
39
+ return manifestPath;
40
+ }
41
+ export async function readManifest(projectRoot) {
42
+ const manifestPath = path.join(projectRoot, MANIFEST_RELATIVE_PATH);
43
+ const raw = await fs.readFile(manifestPath, "utf8");
44
+ const parsed = JSON.parse(raw);
45
+ return parsed;
46
+ }
47
+ export async function manifestExists(projectRoot) {
48
+ return fs.pathExists(path.join(projectRoot, MANIFEST_RELATIVE_PATH));
49
+ }
50
+ export function withStatus(manifest, status) {
51
+ return {
52
+ $schema: manifest.$schema,
53
+ project_metadata: {
54
+ name: manifest.project_metadata.name,
55
+ blueprint_version: manifest.project_metadata.blueprint_version,
56
+ status,
57
+ generated_by: manifest.project_metadata.generated_by,
58
+ generated_at: manifest.project_metadata.generated_at,
59
+ },
60
+ product_blueprints: manifest.product_blueprints,
61
+ execution_dag: manifest.execution_dag,
62
+ feedback_channel: manifest.feedback_channel,
63
+ };
64
+ }
65
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,CAAC,MAAM,sBAAsB,GAAG,2BAA2B,CAAA;AACjE,MAAM,CAAC,MAAM,6BAA6B,GAAG,0CAA0C,CAAA;AAEvF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,WAAW;IACX,UAAU;IACV,UAAU;IACV,gBAAgB;IAChB,SAAS;IACT,WAAW;CACH,CAAA;AAEV,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,CAAU,CAAA;AAyDxF,MAAM,UAAU,oBAAoB,CAAC,WAAmB,EAAE,WAAmB;IAC3E,OAAO;QACL,OAAO,EAAE,mCAAmC;QAC5C,gBAAgB,EAAE;YAChB,IAAI,EAAE,WAAW;YACjB,iBAAiB,EAAE,OAAO;YAC1B,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,iBAAiB;YAC/B,YAAY,EAAE,WAAW;SAC1B;QACD,kBAAkB,EAAE;YAClB,GAAG,EAAE,aAAa;YAClB,GAAG,EAAE,aAAa;YAClB,SAAS,EAAE,mBAAmB;YAC9B,QAAQ,EAAE,CAAC,yBAAyB,CAAC;YACrC,cAAc,EAAE,wBAAwB;SACzC;QACD,aAAa,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QAC9C,gBAAgB,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;KAClD,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,QAAkB;IACzE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAA;IACnE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAA;IAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;IACzD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAA;IACnE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;IACnD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACvC,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAkB,EAAE,MAAsB;IACnE,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,gBAAgB,EAAE;YAChB,IAAI,EAAE,QAAQ,CAAC,gBAAgB,CAAC,IAAI;YACpC,iBAAiB,EAAE,QAAQ,CAAC,gBAAgB,CAAC,iBAAiB;YAC9D,MAAM;YACN,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,YAAY;YACpD,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,YAAY;SACrD;QACD,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;QAC/C,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;KAC5C,CAAA;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type ValidationIssue = {
2
+ readonly code: string;
3
+ readonly message: string;
4
+ readonly path: string;
5
+ };
6
+ export type ValidationReport = {
7
+ readonly ok: boolean;
8
+ readonly issues: readonly ValidationIssue[];
9
+ };
10
+ export declare function validateManifestData(data: unknown): ValidationReport;
11
+ export declare function validateManifestFile(manifestPath: string): Promise<ValidationReport>;
12
+ export declare function checkMermaidSyntax(source: string): ValidationReport;
13
+ export declare function checkReferencedFiles(projectRoot: string, references: readonly string[]): Promise<ValidationReport>;
14
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;CAC5C,CAAA;AA+GD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAWpE;AAED,wBAAsB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAI1F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAKnE;AAED,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAOxH"}
@@ -0,0 +1,137 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ const VALID_PROJECT_STATUSES = new Set([
4
+ "discovery",
5
+ "designed",
6
+ "approved",
7
+ "in_development",
8
+ "blocked",
9
+ "completed",
10
+ ]);
11
+ const VALID_TASK_STATUSES = new Set(["pending", "in_progress", "blocked", "completed"]);
12
+ function issue(code, pathValue, message) {
13
+ return { code, path: pathValue, message };
14
+ }
15
+ function isRecord(value) {
16
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17
+ }
18
+ function stringAt(record, key) {
19
+ const value = record[key];
20
+ return typeof value === "string" ? value : null;
21
+ }
22
+ function arrayAt(record, key) {
23
+ const value = record[key];
24
+ return Array.isArray(value) ? value : null;
25
+ }
26
+ function requireObject(record, key, issues, parent) {
27
+ const value = record[key];
28
+ if (isRecord(value))
29
+ return value;
30
+ issues.push(issue("required_object", `${parent}.${key}`, "Expected an object."));
31
+ return null;
32
+ }
33
+ function requireString(record, key, issues, parent) {
34
+ if (stringAt(record, key) === null) {
35
+ issues.push(issue("required_string", `${parent}.${key}`, "Expected a string."));
36
+ }
37
+ }
38
+ function validateMetadata(root, issues) {
39
+ const metadata = requireObject(root, "project_metadata", issues, "$");
40
+ if (metadata === null)
41
+ return;
42
+ for (const key of ["name", "blueprint_version", "generated_by", "generated_at"]) {
43
+ requireString(metadata, key, issues, "$.project_metadata");
44
+ }
45
+ const status = stringAt(metadata, "status");
46
+ if (status === null || !VALID_PROJECT_STATUSES.has(status)) {
47
+ issues.push(issue("invalid_status", "$.project_metadata.status", "Status is not part of the Oh My PM lifecycle."));
48
+ }
49
+ }
50
+ function validateBlueprints(root, issues) {
51
+ const blueprints = requireObject(root, "product_blueprints", issues, "$");
52
+ if (blueprints === null)
53
+ return;
54
+ for (const key of ["prd", "trd", "db_schema", "execution_plan"]) {
55
+ requireString(blueprints, key, issues, "$.product_blueprints");
56
+ }
57
+ const flows = arrayAt(blueprints, "ui_flows");
58
+ if (flows === null || flows.length === 0 || flows.some((entry) => typeof entry !== "string")) {
59
+ issues.push(issue("invalid_flows", "$.product_blueprints.ui_flows", "Expected at least one flow path string."));
60
+ }
61
+ }
62
+ function validateTask(task, index, issues) {
63
+ if (!isRecord(task)) {
64
+ issues.push(issue("invalid_task", `$.execution_dag.tasks[${index}]`, "Task must be an object."));
65
+ return;
66
+ }
67
+ for (const key of ["id", "spec_reference", "description", "assigned_to"]) {
68
+ requireString(task, key, issues, `$.execution_dag.tasks[${index}]`);
69
+ }
70
+ const status = stringAt(task, "status");
71
+ if (status === null || !VALID_TASK_STATUSES.has(status)) {
72
+ issues.push(issue("invalid_task_status", `$.execution_dag.tasks[${index}].status`, "Task status is invalid."));
73
+ }
74
+ const dependsOn = arrayAt(task, "depends_on");
75
+ if (dependsOn === null || dependsOn.some((entry) => typeof entry !== "string")) {
76
+ issues.push(issue("invalid_dependencies", `$.execution_dag.tasks[${index}].depends_on`, "Dependencies must be strings."));
77
+ }
78
+ const criteria = arrayAt(task, "verification_criteria");
79
+ if (criteria === null || criteria.length === 0 || criteria.some((entry) => typeof entry !== "string")) {
80
+ issues.push(issue("invalid_verification", `$.execution_dag.tasks[${index}].verification_criteria`, "Verification criteria must be non-empty strings."));
81
+ }
82
+ }
83
+ function validateDag(root, issues) {
84
+ const dag = requireObject(root, "execution_dag", issues, "$");
85
+ if (dag === null)
86
+ return;
87
+ requireString(dag, "version", issues, "$.execution_dag");
88
+ const tasks = arrayAt(dag, "tasks");
89
+ if (tasks === null) {
90
+ issues.push(issue("invalid_tasks", "$.execution_dag.tasks", "Expected a task array."));
91
+ return;
92
+ }
93
+ tasks.forEach((task, index) => validateTask(task, index, issues));
94
+ }
95
+ function validateFeedback(root, issues) {
96
+ const feedback = requireObject(root, "feedback_channel", issues, "$");
97
+ if (feedback === null)
98
+ return;
99
+ for (const key of ["blockers", "decisions"]) {
100
+ const value = arrayAt(feedback, key);
101
+ if (value === null)
102
+ issues.push(issue("invalid_feedback", `$.feedback_channel.${key}`, "Expected an array."));
103
+ }
104
+ }
105
+ export function validateManifestData(data) {
106
+ const issues = [];
107
+ if (!isRecord(data)) {
108
+ return { ok: false, issues: [issue("invalid_root", "$", "Manifest root must be an object.")] };
109
+ }
110
+ requireString(data, "$schema", issues, "$");
111
+ validateMetadata(data, issues);
112
+ validateBlueprints(data, issues);
113
+ validateDag(data, issues);
114
+ validateFeedback(data, issues);
115
+ return { ok: issues.length === 0, issues };
116
+ }
117
+ export async function validateManifestFile(manifestPath) {
118
+ const raw = await fs.readFile(manifestPath, "utf8");
119
+ const parsed = JSON.parse(raw);
120
+ return validateManifestData(parsed);
121
+ }
122
+ export function checkMermaidSyntax(source) {
123
+ const firstLine = source.split(/\r?\n/).find((line) => line.trim().length > 0);
124
+ const validPrefixes = ["flowchart", "graph", "sequenceDiagram", "stateDiagram", "erDiagram", "journey", "gantt", "classDiagram"];
125
+ const ok = firstLine !== undefined && validPrefixes.some((prefix) => firstLine.trim().startsWith(prefix));
126
+ return ok ? { ok: true, issues: [] } : { ok: false, issues: [issue("invalid_mermaid", "$", "Mermaid source must start with a supported diagram keyword.")] };
127
+ }
128
+ export async function checkReferencedFiles(projectRoot, references) {
129
+ const issues = [];
130
+ for (const reference of references) {
131
+ const exists = await fs.pathExists(path.join(projectRoot, reference));
132
+ if (!exists)
133
+ issues.push(issue("missing_reference", reference, "Referenced file does not exist."));
134
+ }
135
+ return { ok: issues.length === 0, issues };
136
+ }
137
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ # Oh My PM Architecture
2
+
3
+ Oh My PM is a project-level Product Management harness that installs agent instructions and a manifest contract.
4
+
5
+ ## Components
6
+
7
+ | Component | Responsibility |
8
+ | --- | --- |
9
+ | CLI | Installs templates, initializes `.parkops/`, validates manifests. |
10
+ | OpenCode runtime plugin | Registers five PM agents through OpenCode `config.agent`. |
11
+ | OpenCode templates | `SKILL.md` files for project-level routing and memory. |
12
+ | Claude template | `CLAUDE.md` instructions for Task-based delegation. |
13
+ | OpenAI template | `agents.py` with Agents SDK definitions and handoffs. |
14
+ | Generic template | Portable Markdown instructions for any LLM. |
15
+ | Manifest schema | Contract shape for Oh My PM and Dev-Harness. |
16
+
17
+ ## Pipeline
18
+
19
+ ```text
20
+ User
21
+ -> JC discovery
22
+ -> Hammurabi PRD
23
+ -> DaVinci UX flows
24
+ -> Ada TRD and DB schema
25
+ -> SunTzu execution DAG
26
+ -> JC validation and user approval
27
+ -> Dev-Harness implementation
28
+ ```
29
+
30
+ ## Delegation model
31
+
32
+ JC delegates by lane. Each specialist receives complete context and returns an artifact plus validation evidence. JC never performs specialist work unless the specialist lane is unavailable, and it records that exception as a decision.
33
+
34
+ ## Contract model
35
+
36
+ `.parkops/pm_manifest.json` is the only cross-system contract. It references all blueprints and stores DAG tasks, decisions, and blockers.
37
+
38
+ ## Verification model
39
+
40
+ Every stage has gates:
41
+
42
+ - Artifact exists.
43
+ - Artifact-specific validation passes.
44
+ - Manifest references are consistent.
45
+ - Blockers are open when ambiguity remains.
46
+ - Approval is explicit before development starts.
47
+
48
+ ## Runtime plugin model
49
+
50
+ `src/index.ts` exports the OpenCode plugin. The plugin loads `oh-my-pm.json` from the project root or `~/.config/opencode/`, resolves the active preset, then returns a config hook that merges JC, Hammurabi, DaVinci, Ada, and SunTzu into `opencodeConfig.agent`. The CLI entry point lives in `src/cli.ts` and is exposed as the `oh-my-pm` binary.
51
+
52
+ ## Configuration parity with oh-my-opencode-slim
53
+
54
+ Oh My PM follows the same installation shape: `opencode.jsonc` registers the npm plugin, `oh-my-pm.json` stores plugin-specific presets, and `skills/oh-my-pm/SKILL.md` documents safe configuration changes. The domain differs: this package specializes in Software Product Management rather than general coding orchestration.
@@ -0,0 +1,46 @@
1
+ # Dev-Harness Bridge
2
+
3
+ Dev-Harness consumes `.parkops/pm_manifest.json` as an implementation contract. There are no sync meetings or side-channel agreements. The manifest is the agreement.
4
+
5
+ ## Read path
6
+
7
+ Dev-Harness reads:
8
+
9
+ - `project_metadata.status` to determine whether work is approved.
10
+ - `product_blueprints` to locate PRD, TRD, DB schema, UI flows, and execution plan.
11
+ - `execution_dag.tasks` to schedule work by dependencies.
12
+ - `feedback_channel.decisions` to preserve product and architecture decisions.
13
+
14
+ ## Write path
15
+
16
+ Dev-Harness writes:
17
+
18
+ - task `status` updates as work progresses.
19
+ - blockers in `feedback_channel.blockers` when a task cannot proceed.
20
+ - status `in_development`, `blocked`, or `completed` according to evidence.
21
+
22
+ ## Blocker format
23
+
24
+ ```json
25
+ {
26
+ "id": "blocker_01",
27
+ "raised_by": "dev-harness",
28
+ "description": "The PRD requires offline payments but the TRD only defines Stripe checkout.",
29
+ "proposed_solutions": [
30
+ "Remove offline payments from scope",
31
+ "Add manual invoice flow to TRD and DAG"
32
+ ],
33
+ "status": "open",
34
+ "resolution": ""
35
+ }
36
+ ```
37
+
38
+ ## PM response
39
+
40
+ Oh My PM resolves blockers by updating the relevant product artifacts, adding decisions, changing verification criteria, and marking the blocker resolved with a rationale.
41
+
42
+ ## Integrity rules
43
+
44
+ - Dev-Harness must not invent missing product requirements.
45
+ - Oh My PM must not mark a blocker resolved without updating the artifact that caused the conflict.
46
+ - Both systems must preserve ids so audit history remains stable.
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "./schemas/pm-manifest-schema.json",
3
+ "project_metadata": {
4
+ "name": "team-launch-planner",
5
+ "blueprint_version": "1.0.0",
6
+ "status": "designed",
7
+ "generated_by": "oh-my-pm v1.0.0",
8
+ "generated_at": "2026-06-27T00:00:00.000Z"
9
+ },
10
+ "product_blueprints": {
11
+ "prd": "docs/prd.md",
12
+ "trd": "docs/trd.md",
13
+ "db_schema": "docs/db-schema.md",
14
+ "ui_flows": ["docs/flows/main-flow.md"],
15
+ "execution_plan": "docs/execution-plan.md"
16
+ },
17
+ "execution_dag": {
18
+ "version": "1.0.0",
19
+ "tasks": [
20
+ {
21
+ "id": "task_01_setup_project",
22
+ "depends_on": [],
23
+ "spec_reference": "PRD §3.1",
24
+ "description": "Create the application shell and persistence foundation.",
25
+ "status": "pending",
26
+ "verification_criteria": ["npm run build"],
27
+ "assigned_to": "dev-harness"
28
+ },
29
+ {
30
+ "id": "task_02_launch_plan_crud",
31
+ "depends_on": ["task_01_setup_project"],
32
+ "spec_reference": "PRD §5",
33
+ "description": "Implement create, read, update, and export for launch plans.",
34
+ "status": "pending",
35
+ "verification_criteria": ["npm test"],
36
+ "assigned_to": "dev-harness"
37
+ }
38
+ ]
39
+ },
40
+ "feedback_channel": {
41
+ "blockers": [],
42
+ "decisions": [
43
+ {
44
+ "id": "decision_01",
45
+ "description": "Use manifest-only PM and Dev coordination.",
46
+ "rationale": "The manifest gives both harnesses an auditable contract.",
47
+ "alternatives_considered": ["Chat handoff", "Meeting notes"]
48
+ }
49
+ ]
50
+ }
51
+ }
@@ -0,0 +1,47 @@
1
+ # Product Requirements Document: Team Launch Planner
2
+
3
+ ## 1. Problem
4
+
5
+ Small teams need a shared launch checklist that connects planning, ownership, dependencies, and release readiness without requiring a heavy project-management rollout.
6
+
7
+ ## 2. Users
8
+
9
+ - Founder or product lead who defines launch goals.
10
+ - Engineer who owns implementation tasks.
11
+ - Designer who owns user-facing assets.
12
+ - Operations lead who verifies release readiness.
13
+
14
+ ## 3. Scope
15
+
16
+ ### 3.1 In scope
17
+
18
+ - Create a launch project.
19
+ - Add milestones and owners.
20
+ - Track dependencies between tasks.
21
+ - Display readiness status.
22
+ - Export the launch plan to Markdown.
23
+
24
+ ### 3.2 Out of scope
25
+
26
+ - Real-time chat.
27
+ - Billing.
28
+ - Native mobile apps.
29
+
30
+ ## 4. User stories
31
+
32
+ - As a product lead, I can create a launch plan so the team has a shared source of truth.
33
+ - As an engineer, I can see blocked tasks so I know what cannot proceed.
34
+ - As an operations lead, I can export the plan so stakeholders can review it asynchronously.
35
+
36
+ ## 5. Acceptance Criteria
37
+
38
+ - A user can create a launch plan with title, date, owner, and milestones.
39
+ - A user can mark a task as blocked with a reason.
40
+ - The readiness view shows counts for pending, blocked, and completed tasks.
41
+ - Markdown export includes milestones, owners, dependencies, and blockers.
42
+
43
+ ## 6. Metrics
44
+
45
+ - Time from project creation to first exported plan.
46
+ - Percentage of launches with zero unresolved blockers by release date.
47
+ - Weekly active launch projects.
@@ -0,0 +1,75 @@
1
+ # Installation Guide
2
+
3
+ ## Requirements
4
+
5
+ - Node.js 20 or newer.
6
+ - Bun available for `bunx oh-my-pm` usage.
7
+ - A project directory where Oh My PM may write `.parkops/`, `.opencode/`, `AGENTS.md`, and optional platform files.
8
+
9
+ ## Install through bunx
10
+
11
+ ```bash
12
+ bunx oh-my-pm init
13
+ bunx oh-my-pm install
14
+ ```
15
+
16
+ `init` creates `.parkops/pm_manifest.json` and copies the schema into `.parkops/schemas/pm-manifest-schema.json`.
17
+
18
+ `install` writes the OpenCode runtime plugin configuration plus project skill files:
19
+
20
+ ```text
21
+ .opencode/skills/jc/SKILL.md
22
+ .opencode/skills/hammurabi/SKILL.md
23
+ .opencode/skills/davinci/SKILL.md
24
+ .opencode/skills/ada/SKILL.md
25
+ .opencode/skills/suntzu/SKILL.md
26
+ .opencode/skills/oh-my-pm/SKILL.md
27
+ opencode.jsonc
28
+ oh-my-pm.json
29
+ AGENTS.md
30
+ ```
31
+
32
+
33
+ ## Global OpenCode install
34
+
35
+ ```bash
36
+ bunx oh-my-pm install --global
37
+ ```
38
+
39
+ This installs into `~/.config/opencode/`, merges `"oh-my-pm@latest"` into the existing `plugin` array, writes `oh-my-pm.json`, and installs all six skills under `skills/`. Existing files are backed up with `.oh-my-pm.backup`.
40
+
41
+ ## Optional platform outputs
42
+
43
+ ```bash
44
+ bunx oh-my-pm install --claude
45
+ bunx oh-my-pm install --openai
46
+ bunx oh-my-pm install --generic
47
+ bunx oh-my-pm install --all
48
+ ```
49
+
50
+ These commands install `CLAUDE.md`, `agents.py`, or `OH_MY_PM_AGENTS.md` alongside the OpenCode runtime plugin configuration.
51
+
52
+ ## Template generation
53
+
54
+ Use generation when you want to inspect templates before installing them:
55
+
56
+ ```bash
57
+ bunx oh-my-pm generate opencode
58
+ bunx oh-my-pm generate claude
59
+ bunx oh-my-pm generate openai
60
+ bunx oh-my-pm generate generic
61
+ ```
62
+
63
+ Generated templates are written under `.parkops/generated/{platform}`.
64
+
65
+ ## Validation
66
+
67
+ ```bash
68
+ bunx oh-my-pm validate
69
+ ```
70
+
71
+ Validation checks the shape of `.parkops/pm_manifest.json`, lifecycle status, blueprint paths, DAG tasks, verification criteria, blockers, and decisions.
72
+
73
+ ## OpenCode runtime plugin
74
+
75
+ The generated `opencode.jsonc` uses OpenCode's `plugin` and `agent` fields. The `plugin` entry loads `oh-my-pm@latest`; the runtime plugin injects the five PM agents through the OpenCode config hook. `oh-my-pm.json` stores model presets, mirroring the `oh-my-opencode-slim.json` pattern. The `agent` block remains available for project-level model overrides.
@@ -0,0 +1,27 @@
1
+ # Manifest Lifecycle
2
+
3
+ Oh My PM and Dev-Harness coordinate through lifecycle status in `.parkops/pm_manifest.json`.
4
+
5
+ ## States
6
+
7
+ | Status | Owner | Meaning | Exit condition |
8
+ | --- | --- | --- | --- |
9
+ | discovery | Oh My PM | JC is gathering product intent and constraints. | Product scope is clear enough to design. |
10
+ | designed | Oh My PM | PRD, TRD, flows, DB schema, and execution DAG are drafted and validated. | User explicitly approves the design. |
11
+ | approved | User and Oh My PM | The manifest is accepted as the development contract. | Dev-Harness starts implementation. |
12
+ | in_development | Dev-Harness | Implementation is in progress against pending DAG tasks. | All tasks complete or a blocker appears. |
13
+ | blocked | Dev-Harness or Oh My PM | A contradiction, missing dependency, or infeasible criterion halted progress. | Oh My PM resolves the blocker. |
14
+ | completed | Dev-Harness | Every DAG task is completed and verification evidence exists. | Release or archive. |
15
+
16
+ ## Transition rules
17
+
18
+ - `discovery` can move to `designed` only after every required artifact path is known.
19
+ - `designed` can move to `approved` only after explicit user approval.
20
+ - `approved` can move to `in_development` when Dev-Harness begins execution.
21
+ - Any active state can move to `blocked` if an open blocker prevents honest execution.
22
+ - `blocked` can move back to `designed`, `approved`, or `in_development` depending on the resolved scope.
23
+ - `completed` requires every DAG task status to be `completed`.
24
+
25
+ ## Blocker discipline
26
+
27
+ A blocker must include an id, raiser, description, proposed solutions, status, and resolution. Do not delete blockers. Mark them resolved and write the resolution.
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://unpkg.com/oh-my-pm@latest/oh-my-pm.schema.json",
4
+ "title": "Oh My PM Plugin Configuration",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["preset", "presets"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "preset": { "type": "string", "minLength": 1 },
11
+ "presets": {
12
+ "type": "object",
13
+ "additionalProperties": { "$ref": "#/$defs/preset" },
14
+ "minProperties": 1
15
+ }
16
+ },
17
+ "$defs": {
18
+ "preset": {
19
+ "type": "object",
20
+ "additionalProperties": { "$ref": "#/$defs/agentPreset" }
21
+ },
22
+ "agentPreset": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "required": ["model"],
26
+ "properties": {
27
+ "model": { "type": "string", "minLength": 1 },
28
+ "variant": { "type": "string", "minLength": 1 }
29
+ }
30
+ }
31
+ }
32
+ }