forgeos 0.1.0-alpha.63 → 0.1.0-alpha.64

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 (63) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/docs/agent-fabric.md +252 -0
  4. package/package.json +7 -4
  5. package/schemas/agent-fabric/v0.1/control-event.schema.json +281 -0
  6. package/scripts/field-test-forgeos.mjs +11 -2
  7. package/src/forge/_generated/releaseManifest.json +1 -1
  8. package/src/forge/_generated/releaseManifest.ts +3 -3
  9. package/src/forge/agent-adapters/index.ts +18 -14
  10. package/src/forge/agent-adapters/types.ts +1 -1
  11. package/src/forge/agent-fabric/adapter.ts +131 -0
  12. package/src/forge/agent-fabric/authority.ts +298 -0
  13. package/src/forge/agent-fabric/canonical.ts +135 -0
  14. package/src/forge/agent-fabric/conductor.ts +754 -0
  15. package/src/forge/agent-fabric/dictionary.ts +12 -0
  16. package/src/forge/agent-fabric/errors.ts +32 -0
  17. package/src/forge/agent-fabric/hardened-conductor.ts +485 -0
  18. package/src/forge/agent-fabric/hardened-reducer.ts +211 -0
  19. package/src/forge/agent-fabric/index.ts +18 -0
  20. package/src/forge/agent-fabric/journal.ts +116 -0
  21. package/src/forge/agent-fabric/local-approval-window.ts +169 -0
  22. package/src/forge/agent-fabric/local-coding-worker.ts +190 -0
  23. package/src/forge/agent-fabric/local-control-store.ts +239 -0
  24. package/src/forge/agent-fabric/local-paths.ts +18 -0
  25. package/src/forge/agent-fabric/local-task-contract.ts +142 -0
  26. package/src/forge/agent-fabric/local-task-inbox.ts +199 -0
  27. package/src/forge/agent-fabric/local-task-server.ts +207 -0
  28. package/src/forge/agent-fabric/local-task-service.ts +494 -0
  29. package/src/forge/agent-fabric/p0a.ts +104 -0
  30. package/src/forge/agent-fabric/p0b-model-adapter.ts +404 -0
  31. package/src/forge/agent-fabric/planning.ts +155 -0
  32. package/src/forge/agent-fabric/reducer.ts +863 -0
  33. package/src/forge/agent-fabric/resource-ledger.ts +266 -0
  34. package/src/forge/agent-fabric/serialized-local-adapter.ts +60 -0
  35. package/src/forge/agent-fabric/types.ts +424 -0
  36. package/src/forge/agent-fabric/validation.ts +500 -0
  37. package/src/forge/agent-memory/bridge.ts +82 -52
  38. package/src/forge/agent-memory/mcp.ts +59 -9
  39. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +12 -113
  40. package/src/forge/cli/commands.ts +4 -0
  41. package/src/forge/cli/fabric.ts +83 -0
  42. package/src/forge/cli/main.ts +7 -0
  43. package/src/forge/cli/new.ts +16 -4
  44. package/src/forge/cli/parse.ts +21 -0
  45. package/src/forge/cli/verify.ts +4 -1
  46. package/src/forge/compiler/app-graph/tsconfig-hash.ts +41 -4
  47. package/src/forge/compiler/package-graph/dts-extractor.ts +14 -1
  48. package/src/forge/impact/index.ts +18 -21
  49. package/src/forge/runtime/ai/providers.ts +19 -4
  50. package/src/forge/version.ts +1 -1
  51. package/templates/agent-workroom/package.json +1 -0
  52. package/templates/agent-workroom/pnpm-workspace.yaml +2 -0
  53. package/templates/b2b-support-web/package.json +1 -0
  54. package/templates/b2b-support-web/pnpm-workspace.yaml +2 -0
  55. package/templates/b2b-support-web/web/package.json +1 -1
  56. package/templates/minimal-web/package.json +1 -0
  57. package/templates/minimal-web/pnpm-workspace.yaml +2 -0
  58. package/templates/nuxt-web/.yarnrc.yml +1 -0
  59. package/templates/nuxt-web/package.json +1 -0
  60. package/templates/nuxt-web/pnpm-workspace.yaml +2 -0
  61. package/templates/nuxt-web/web/package.json +1 -0
  62. package/templates/vendor-access/package.json +1 -0
  63. package/templates/vendor-access/pnpm-workspace.yaml +2 -0
@@ -0,0 +1,135 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AgentFabricError } from "./errors.ts";
3
+ import type { Digest, DigestFunction } from "./types.ts";
4
+
5
+ /**
6
+ * P0a canonical JSON profile.
7
+ *
8
+ * This profile is intentionally explicit and deterministic for the current
9
+ * TypeScript/JavaScript reference implementation. Cross-language JCS
10
+ * conformance is a separate protocol profile and is not claimed here.
11
+ */
12
+ export const P0A_CANONICALIZATION_PROFILE = "forge-canonical-json/v0.1" as const;
13
+
14
+ function canonicalizationFailure(message: string): never {
15
+ throw new AgentFabricError("AF_CANONICALIZATION_FAILED", message);
16
+ }
17
+
18
+ function assertJsonObjectShape(value: object): void {
19
+ const prototype = Object.getPrototypeOf(value);
20
+ if (prototype !== Object.prototype && prototype !== null) {
21
+ canonicalizationFailure("Canonical objects must have Object.prototype or null prototype");
22
+ }
23
+
24
+ for (const key of Reflect.ownKeys(value)) {
25
+ if (typeof key !== "string") {
26
+ canonicalizationFailure("Canonical objects cannot contain symbol properties");
27
+ }
28
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
29
+ if (!descriptor?.enumerable) {
30
+ canonicalizationFailure(`Canonical object property ${key} must be enumerable`);
31
+ }
32
+ if (!("value" in descriptor)) {
33
+ canonicalizationFailure(`Canonical object property ${key} cannot be an accessor`);
34
+ }
35
+ }
36
+ }
37
+
38
+ function assertJsonArrayShape(value: readonly unknown[]): void {
39
+ if (Object.getPrototypeOf(value) !== Array.prototype) {
40
+ canonicalizationFailure("Canonical arrays must have Array.prototype");
41
+ }
42
+
43
+ const ownKeys = Reflect.ownKeys(value);
44
+ const expectedIndexKeys = new Set(Array.from({ length: value.length }, (_, index) => String(index)));
45
+
46
+ for (const key of ownKeys) {
47
+ if (key === "length") continue;
48
+ if (typeof key !== "string" || !expectedIndexKeys.has(key)) {
49
+ canonicalizationFailure("Canonical arrays cannot contain extra or symbol properties");
50
+ }
51
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
52
+ if (!descriptor?.enumerable || !("value" in descriptor)) {
53
+ canonicalizationFailure(`Canonical array index ${key} must be an enumerable data property`);
54
+ }
55
+ }
56
+
57
+ for (let index = 0; index < value.length; index += 1) {
58
+ if (!Object.prototype.hasOwnProperty.call(value, index)) {
59
+ canonicalizationFailure("Canonical arrays cannot be sparse");
60
+ }
61
+ }
62
+ }
63
+
64
+ function normalize(value: unknown, seen: Set<object>): unknown {
65
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
66
+ return value;
67
+ }
68
+
69
+ if (typeof value === "number") {
70
+ if (!Number.isFinite(value)) {
71
+ canonicalizationFailure("Canonical values cannot contain non-finite numbers");
72
+ }
73
+ return Object.is(value, -0) ? 0 : value;
74
+ }
75
+
76
+ if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol") {
77
+ canonicalizationFailure(`Unsupported canonical value type: ${typeof value}`);
78
+ }
79
+
80
+ if (typeof value === "bigint") {
81
+ canonicalizationFailure("BigInt values must be encoded as strings before canonicalization");
82
+ }
83
+
84
+ if (Array.isArray(value)) {
85
+ if (seen.has(value)) canonicalizationFailure("Canonical values cannot be cyclic");
86
+ assertJsonArrayShape(value);
87
+ seen.add(value);
88
+ const normalized: unknown[] = [];
89
+ for (let index = 0; index < value.length; index += 1) {
90
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
91
+ if (!descriptor || !("value" in descriptor)) {
92
+ seen.delete(value);
93
+ canonicalizationFailure(`Canonical array index ${index} must be an own data property`);
94
+ }
95
+ normalized[index] = normalize(descriptor.value, seen);
96
+ }
97
+ seen.delete(value);
98
+ return normalized;
99
+ }
100
+
101
+ if (typeof value === "object") {
102
+ if (seen.has(value)) canonicalizationFailure("Canonical values cannot be cyclic");
103
+ assertJsonObjectShape(value);
104
+ seen.add(value);
105
+ const record = value as Record<string, unknown>;
106
+ // A null-prototype accumulator is required so an own `__proto__` key is
107
+ // preserved as data rather than invoking Object.prototype's legacy setter.
108
+ const normalized = Object.create(null) as Record<string, unknown>;
109
+ for (const key of Object.keys(record).sort()) {
110
+ if (record[key] === undefined) {
111
+ canonicalizationFailure(`Canonical object property ${key} is undefined`);
112
+ }
113
+ normalized[key] = normalize(record[key], seen);
114
+ }
115
+ seen.delete(value);
116
+ return normalized;
117
+ }
118
+
119
+ canonicalizationFailure("Unsupported canonical value");
120
+ }
121
+
122
+ export function stableStringify(value: unknown): string {
123
+ return JSON.stringify(normalize(value, new Set<object>()));
124
+ }
125
+
126
+ export function sha256Digest(canonicalValue: string): Digest {
127
+ return `sha256:${createHash("sha256").update(canonicalValue).digest("hex")}`;
128
+ }
129
+
130
+ export function digestCanonical(
131
+ value: unknown,
132
+ digest: DigestFunction,
133
+ ): Digest {
134
+ return digest(stableStringify(value));
135
+ }