diff --git a/compiler/src/parser.ts b/compiler/src/parser.ts index 9a7d15e..3ccb289 100644 --- a/compiler/src/parser.ts +++ b/compiler/src/parser.ts @@ -324,15 +324,13 @@ function parseSpeck(lines: string[], startIndex: number): SpeckNode | null { const name = headerMatch[1]; const members: MemberNode[] = []; - // Cycle 61: clear static metadata fields at the start of each parse - // so per-speck directives don't leak between parse calls. This is the - // pre-existing static-field-hack pattern for proto_package / go_package - // (see spec-compiler-dogfood skill anti-pattern). Refactoring to a - // local-object approach is tracked as a separate cleanup; for now - // resetting the fields here is the minimal-touch fix. - (parseSpeck as any)._protoPackage = undefined; - (parseSpeck as any)._goPackage = undefined; - (parseSpeck as any)._eventSuffix = undefined; + // Cycle 73: refactored from static-field hack to local-object pattern. + // Previously, proto_package / go_package / event_suffix were stored + // on (parseSpeck as any)._protoPackage etc — static function fields + // that leaked between parse calls. Now collected in a local metadata + // object and spread into the return value. No reset needed because + // the object is local to this invocation. + const metadata: { protoPackage?: string; goPackage?: string; eventSuffix?: string } = {}; let i = startIndex + 1; let braceCount = 1; @@ -357,11 +355,11 @@ function parseSpeck(lines: string[], startIndex: number): SpeckNode | null { // Strip surrounding quotes if present const value = metaMatch[2].trim().replace(/^['"]|['"]$/g, ''); if (metaMatch[1] === 'proto_package') { - (parseSpeck as any)._protoPackage = value; + metadata.protoPackage = value; } else if (metaMatch[1] === 'go_package') { - (parseSpeck as any)._goPackage = value; + metadata.goPackage = value; } else if (metaMatch[1] === 'event_suffix') { - (parseSpeck as any)._eventSuffix = value; + metadata.eventSuffix = value; } i++; continue; @@ -435,9 +433,9 @@ function parseSpeck(lines: string[], startIndex: number): SpeckNode | null { } return { type: 'speck', name, members, - protoPackage: (parseSpeck as any)._protoPackage, - goPackage: (parseSpeck as any)._goPackage, - eventSuffix: (parseSpeck as any)._eventSuffix }; + protoPackage: metadata.protoPackage, + goPackage: metadata.goPackage, + eventSuffix: metadata.eventSuffix }; } function findBlockEnd(lines: string[], startIndex: number, startBraceCount: number): number {