ahead-pi 0.2.0 → 0.3.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 (102) hide show
  1. package/README.md +29 -9
  2. package/dist/ahead_wasm.wasm +0 -0
  3. package/generated/corrective-debugging/ai-audit.md +39 -0
  4. package/generated/corrective-debugging/ai-review.md +46 -0
  5. package/generated/corrective-debugging/characterize.md +53 -0
  6. package/generated/corrective-debugging/conclude.md +59 -0
  7. package/generated/corrective-debugging/correction.md +53 -0
  8. package/generated/corrective-debugging/deploy.md +38 -0
  9. package/generated/corrective-debugging/human-review.md +45 -0
  10. package/generated/corrective-debugging/implement.md +42 -0
  11. package/generated/corrective-debugging/investigate.md +59 -0
  12. package/generated/corrective-debugging/manifest.json +30 -0
  13. package/generated/corrective-debugging/model.md +53 -0
  14. package/generated/corrective-debugging/outcome.md +38 -0
  15. package/generated/corrective-debugging/plan.md +53 -0
  16. package/generated/corrective-debugging/verify.md +47 -0
  17. package/generated/decision/compare.md +45 -0
  18. package/generated/decision/criteria.md +45 -0
  19. package/generated/decision/decide.md +45 -0
  20. package/generated/decision/frame.md +45 -0
  21. package/generated/decision/manifest.json +21 -0
  22. package/generated/decision/options.md +47 -0
  23. package/generated/decision/publish.md +38 -0
  24. package/generated/decision/research.md +45 -0
  25. package/generated/internal-improvement/ai-audit.md +39 -0
  26. package/generated/internal-improvement/ai-review.md +46 -0
  27. package/generated/internal-improvement/baseline.md +46 -0
  28. package/generated/internal-improvement/decision.md +45 -0
  29. package/generated/internal-improvement/deploy.md +38 -0
  30. package/generated/internal-improvement/human-review.md +45 -0
  31. package/generated/internal-improvement/implement.md +42 -0
  32. package/generated/internal-improvement/invariants.md +38 -0
  33. package/generated/internal-improvement/manifest.json +29 -0
  34. package/generated/internal-improvement/options.md +47 -0
  35. package/generated/internal-improvement/outcome.md +38 -0
  36. package/generated/internal-improvement/plan.md +53 -0
  37. package/generated/internal-improvement/target.md +45 -0
  38. package/generated/internal-improvement/verify.md +45 -0
  39. package/generated/investigation/bound.md +45 -0
  40. package/generated/investigation/conclude.md +45 -0
  41. package/generated/investigation/explore.md +60 -0
  42. package/generated/investigation/frame.md +45 -0
  43. package/generated/investigation/gather.md +45 -0
  44. package/generated/investigation/manifest.json +21 -0
  45. package/generated/investigation/synthesize.md +51 -0
  46. package/generated/operational-stabilization/assess.md +46 -0
  47. package/generated/operational-stabilization/execute-observe.md +45 -0
  48. package/generated/operational-stabilization/manifest.json +19 -0
  49. package/generated/operational-stabilization/monitor.md +45 -0
  50. package/generated/operational-stabilization/outcome.md +38 -0
  51. package/generated/operational-stabilization/respond.md +40 -0
  52. package/generated/operational-stabilization/verify-recovery.md +45 -0
  53. package/generated/product-change/ai-audit.md +12 -6
  54. package/generated/product-change/ai-review.md +20 -7
  55. package/generated/product-change/decision.md +16 -4
  56. package/generated/product-change/define.md +9 -4
  57. package/generated/product-change/deploy.md +9 -4
  58. package/generated/product-change/human-review.md +16 -4
  59. package/generated/product-change/implement.md +14 -5
  60. package/generated/product-change/manifest.json +9 -4
  61. package/generated/product-change/options.md +16 -4
  62. package/generated/product-change/outcome.md +9 -4
  63. package/generated/product-change/plan.md +22 -4
  64. package/generated/product-change/questions.md +22 -4
  65. package/generated/product-change/research.md +16 -4
  66. package/generated/product-change/verify.md +9 -4
  67. package/generated/recommended-skills.json +24 -0
  68. package/generated/reference/CONSTITUTION.md +43 -0
  69. package/generated/reference/docs/acceptable-ai-use.md +217 -0
  70. package/generated/reference/docs/design/adapted-skill-guidance.md +27 -0
  71. package/generated/reference/docs/design/debugging-and-operations.md +119 -0
  72. package/generated/reference/docs/design/executable-workflows.md +122 -0
  73. package/generated/reference/docs/design/instruction-authoring.md +28 -0
  74. package/generated/reference/docs/design/process-taxonomy.md +144 -0
  75. package/generated/reference/docs/design/review-workbench.md +37 -0
  76. package/generated/reference/docs/engineering-practice.md +163 -0
  77. package/generated/reference/docs/evidence/evidence-standard.md +123 -0
  78. package/generated/reference/docs/evidence/research-map.md +98 -0
  79. package/generated/reference/docs/rationale.md +210 -0
  80. package/generated/reference/docs/recommended-skills.md +19 -0
  81. package/generated/reference/docs/references/pragmatic-programmer-page-index.md +113 -0
  82. package/generated/reference/docs/references/submitted-engineering-notes.md +306 -0
  83. package/generated/reference/docs/releasing-pi.md +89 -0
  84. package/generated/reference/docs/workflows/README.md +142 -0
  85. package/generated/reference/docs/workflows/corrective-debugging.md +221 -0
  86. package/generated/reference/docs/workflows/decision.md +149 -0
  87. package/generated/reference/docs/workflows/internal-improvement.md +219 -0
  88. package/generated/reference/docs/workflows/investigation.md +161 -0
  89. package/generated/reference/docs/workflows/operational-stabilization.md +187 -0
  90. package/generated/reference/docs/workflows/product-change.md +216 -0
  91. package/generated/reference/index.json +298 -0
  92. package/package.json +36 -25
  93. package/src/engine.ts +26 -7
  94. package/src/flow-guides.ts +168 -0
  95. package/src/guidance.ts +220 -72
  96. package/src/index.ts +696 -140
  97. package/src/reference-viewer.ts +73 -0
  98. package/src/reference.ts +107 -0
  99. package/src/review.ts +360 -0
  100. package/src/skills.ts +133 -0
  101. package/src/storage.ts +77 -13
  102. package/src/types.ts +1 -0
package/src/storage.ts CHANGED
@@ -11,9 +11,11 @@ interface CurrentRunPointer {
11
11
 
12
12
  export class RunStore {
13
13
  readonly aheadDirectory: string;
14
+ readonly projectRoot: string;
14
15
 
15
- constructor(readonly projectRoot: string) {
16
- this.aheadDirectory = join(projectRoot, ".ahead");
16
+ constructor(rootPath: string) {
17
+ this.projectRoot = rootPath;
18
+ this.aheadDirectory = join(rootPath, ".ahead");
17
19
  }
18
20
 
19
21
  newRunId(): string {
@@ -23,19 +25,20 @@ export class RunStore {
23
25
 
24
26
  async loadCurrent(): Promise<Run | undefined> {
25
27
  try {
26
- const pointer = JSON.parse(await readFile(join(this.aheadDirectory, "current.json"), "utf8")) as CurrentRunPointer;
27
- if (pointer.api_version !== "ahead.current/v0" || !pointer.run_id) {
28
- throw new Error("invalid .ahead/current.json");
29
- }
28
+ const pointer = parseCurrentRunPointer(
29
+ await readFile(join(this.aheadDirectory, "current.json"), "utf8"),
30
+ );
30
31
  return this.load(pointer.run_id);
31
32
  } catch (error) {
32
- if (isMissing(error)) return undefined;
33
+ if (isMissing(error)) {
34
+ return undefined;
35
+ }
33
36
  throw error;
34
37
  }
35
38
  }
36
39
 
37
40
  async load(runId: string): Promise<Run> {
38
- return JSON.parse(await readFile(this.runPath(runId), "utf8")) as Run;
41
+ return parseRun(await readFile(this.runPath(runId), "utf8"));
39
42
  }
40
43
 
41
44
  async save(run: Run, makeCurrent = true): Promise<void> {
@@ -48,7 +51,13 @@ export class RunStore {
48
51
 
49
52
  artifactPath(run: Run, phase: string, kind: string): { absolute: string; relative: string } {
50
53
  const sequence = String(run.events.length + 1).padStart(4, "0");
51
- const absolute = join(this.aheadDirectory, "runs", run.id, "artifacts", `${sequence}-${phase}-${kind}.md`);
54
+ const absolute = join(
55
+ this.aheadDirectory,
56
+ "runs",
57
+ run.id,
58
+ "artifacts",
59
+ `${sequence}-${phase}-${kind}.md`,
60
+ );
52
61
  return { absolute, relative: relative(this.projectRoot, absolute) };
53
62
  }
54
63
 
@@ -62,15 +71,28 @@ export class RunStore {
62
71
  await writeFile(resolved, `${content.trim()}\n`, { encoding: "utf8", flag: "wx" });
63
72
  }
64
73
 
74
+ async readArtifact(path: string): Promise<string> {
75
+ const resolved = resolve(this.projectRoot, path);
76
+ const artifactsRoot = resolve(this.aheadDirectory, "runs");
77
+ if (!resolved.startsWith(`${artifactsRoot}/`)) {
78
+ throw new Error("artifact path escaped .ahead/runs");
79
+ }
80
+ return readFile(resolved, "utf8");
81
+ }
82
+
65
83
  private runPath(runId: string): string {
66
- if (!/^[A-Za-z0-9._-]+$/.test(runId)) throw new Error("unsafe AHEAD run id");
84
+ if (!/^[A-Za-z0-9._-]+$/.test(runId)) {
85
+ throw new Error("unsafe AHEAD run id");
86
+ }
67
87
  return join(this.aheadDirectory, "runs", runId, "run.json");
68
88
  }
69
89
  }
70
90
 
71
91
  export function humanActor(cwd: string): Actor {
72
92
  const explicit = process.env.AHEAD_HUMAN_IDENTITY?.trim();
73
- if (explicit) return { kind: "human", identity: explicit };
93
+ if (explicit) {
94
+ return { kind: "human", identity: explicit };
95
+ }
74
96
  for (const key of ["user.email", "user.name"]) {
75
97
  try {
76
98
  const value = execFileSync("git", ["config", key], {
@@ -78,7 +100,9 @@ export function humanActor(cwd: string): Actor {
78
100
  encoding: "utf8",
79
101
  stdio: ["ignore", "pipe", "ignore"],
80
102
  }).trim();
81
- if (value) return { kind: "human", identity: value };
103
+ if (value) {
104
+ return { kind: "human", identity: value };
105
+ }
82
106
  } catch {
83
107
  // Fall through to the next local identity source.
84
108
  }
@@ -93,7 +117,9 @@ export function projectRoot(cwd: string): string {
93
117
  encoding: "utf8",
94
118
  stdio: ["ignore", "pipe", "ignore"],
95
119
  }).trim();
96
- if (root) return root;
120
+ if (root) {
121
+ return root;
122
+ }
97
123
  } catch {
98
124
  // AHEAD can also persist beside work that is not yet in Git.
99
125
  }
@@ -110,3 +136,41 @@ async function atomicJson(path: string, value: unknown): Promise<void> {
110
136
  function isMissing(error: unknown): boolean {
111
137
  return !!error && typeof error === "object" && "code" in error && error.code === "ENOENT";
112
138
  }
139
+
140
+ function parseCurrentRunPointer(content: string): CurrentRunPointer {
141
+ const value: unknown = JSON.parse(content);
142
+ if (
143
+ !isRecord(value) ||
144
+ value.api_version !== "ahead.current/v0" ||
145
+ typeof value.run_id !== "string" ||
146
+ value.run_id.length === 0
147
+ ) {
148
+ throw new Error("invalid .ahead/current.json");
149
+ }
150
+ return { api_version: value.api_version, run_id: value.run_id };
151
+ }
152
+
153
+ function parseRun(content: string): Run {
154
+ const value: unknown = JSON.parse(content);
155
+ if (!isRun(value)) {
156
+ throw new Error("invalid AHEAD run record");
157
+ }
158
+ return value;
159
+ }
160
+
161
+ function isRun(value: unknown): value is Run {
162
+ return (
163
+ isRecord(value) &&
164
+ typeof value.api_version === "string" &&
165
+ typeof value.id === "string" &&
166
+ typeof value.title === "string" &&
167
+ typeof value.workflow_id === "string" &&
168
+ typeof value.workflow_version === "string" &&
169
+ typeof value.owner === "string" &&
170
+ Array.isArray(value.events)
171
+ );
172
+ }
173
+
174
+ function isRecord(value: unknown): value is Record<string, unknown> {
175
+ return typeof value === "object" && value !== null;
176
+ }
package/src/types.ts CHANGED
@@ -13,6 +13,7 @@ export interface ArtifactDefinition {
13
13
  actor: ActorRule;
14
14
  required: boolean;
15
15
  independent_of?: string;
16
+ same_as?: string;
16
17
  }
17
18
 
18
19
  export interface PhaseDefinition {