Skip to content

Wire up ADS submodule, codegen, runtime path aliases (no behavioral swap yet)#445

Open
kevinelliott wants to merge 6 commits into
masterfrom
dsl/adopt-v1
Open

Wire up ADS submodule, codegen, runtime path aliases (no behavioral swap yet)#445
kevinelliott wants to merge 6 commits into
masterfrom
dsl/adopt-v1

Conversation

@kevinelliott
Copy link
Copy Markdown
Contributor

@kevinelliott kevinelliott commented May 28, 2026

Summary

Integrates airframesio/acars-decoder as a git submodule and wires up the codegen toolchain, without replacing any hand-written plugin yet. Behavior is identical to master after this PR — every one of the 407 existing tests still passes, byte-for-byte.

This is the foundation PR for Stage 2 of the cross-language ACARS decoder unification. The actual swap (registering generated plugins in MessageDecoder) is deferred to a follow-up because the emitter design needs one more pass before swapping is safe (see "What's deferred" below).

What landed

  • Submodule: vendor/airframes-decoder pinned to init/ads-v1.
  • tsconfig path aliases:
    • @airframes/ads-runtime-tsvendor/airframes-decoder/runtimes/typescript/index.ts
    • @airframes/ads-runtime-ts/helpersvendor/airframes-decoder/runtimes/typescript/helpers.ts
    • @airframes/ads-runtime-ts/escape_hatchesvendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts
  • npm scripts:
    • npm run ads:codegen-build — installs + builds the codegen tool
    • npm run ads:generate — emits lib/plugins/generated/*.ts from spec YAML
    • npm run ads:check — fails if lib/plugins/generated/ is out-of-date
  • Generated tree committed: 68 plugins under lib/plugins/generated/. Committed (not gitignored) so contributors don't need the codegen toolchain to build/test, and reviewers see exactly what the runtime would use.
  • ESLint excludes: vendor/** and lib/plugins/generated/** (avoid linting third-party code and auto-generated source).
  • Jest excludes: /vendor/ (skip vendored submodule's own test files).
  • CI workflow: .github/workflows/ads-check.yml calls the central reusable codegen-check.yml from airframes-decoder. Single source of CI logic across all three language repos.

What's deferred (to a follow-up "Stage 2.5" PR)

The emitter currently double-bookkeeps raw fields: it auto-emits result.raw.<fieldName> = value from the spec's fields block AND then formatter calls write to raw under formatter-canonical keys (position, altitude, etc.). The original hand-written plugins only do the latter. Adopting the generated plugins as-is would produce extra raw entries that diverge from the existing test expectations.

The fix is in the emitter (vendor/airframes-decoder/codegen/src/emit-typescript.ts): track which raw keys the formatter writes and suppress the auto-emit for those keys. Once that lands in airframes-decoder and propagates here via submodule bump, the registration swap is safe.

The original lib/utils/*.ts helpers also stay in place until then; once the swap happens, they'll be removed in favor of the vendored copies.

Test plan

  • npm test — 407 / 416 tests pass (9 skipped, matches baseline)
  • npm run ads:codegen-build succeeds
  • npm run ads:generate produces clean output; no diff vs committed
  • tsc resolves the path aliases (verified by running the test suite, which goes through the same module resolution)
  • CI runs the new ads-check workflow on this PR (verifies generated tree stays in sync)

Related

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Added CI workflow to validate ADS-related generated code.
    • Added vendored ADS decoder and scripts to build/generate/check generated artifacts.
    • Updated tooling (lint, test, TypeScript) to ignore and map vendored/generated code.
  • Refactor

    • Decoder now integrates generated plugin implementations for several labels.
    • Added an empty escape-hatch module placeholder for future plugins.

Review Change Stack

…wap yet)

Sets the foundation for the cross-language Airframes Decoder Spec (ADS)
unification by integrating airframes-decoder into this repo as a git
submodule, without yet replacing any hand-written plugins. Behavior is
identical to master after this PR.

What this PR does:

- Add `vendor/airframes-decoder` as a git submodule (pinned to its
  init/ads-v1 branch).
- Add tsconfig path aliases (`@airframes/ads-runtime-ts` and friends)
  resolving into the submodule's runtimes/typescript/.
- Add npm scripts:
    npm run ads:codegen-build  — build the codegen tool
    npm run ads:generate       — emit lib/plugins/generated/*.ts from spec
    npm run ads:check          — fail if generated tree is out-of-date
- Generate the 68 plugins into lib/plugins/generated/ and commit them
  (avoids requiring the codegen toolchain in every contributor's env).
- Exclude vendor/ and lib/plugins/generated/ from ESLint.
- Exclude vendor/ from Jest test discovery.
- Add .github/workflows/ads-check.yml that calls the central reusable
  `codegen-check.yml` workflow (single source of CI logic across repos).

What this PR does NOT do (intentionally — separate Stage 2.5 PR):

- Does NOT register generated plugins in MessageDecoder.ts. The current
  emitter double-bookkeeps `raw` fields (field assignments + formatter
  writes), which would diverge from existing test expectations. Resolving
  this needs an emitter design pass (track which raw keys the formatter
  owns, suppress auto-emit in those cases) before a behavioral swap
  is safe.
- Does NOT remove the original lib/utils/*.ts helpers yet. The runtime
  is duplicated between this repo and the submodule until Stage 2.5
  swaps imports.

Verification:
- All 407 existing tests pass.
- `npm run ads:generate` produces 68 .ts files with no diff vs committed.
- Generated files compile against `@airframes/ads-runtime-ts` path
  aliases (resolution verified via tsc paths).

See airframesio/acars-decoder#1 for the central spec, codegen, runtimes,
docs, and 288-sample corpus this submodule references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 28, 2026 06:26
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Warning

Review limit reached

@kevinelliott, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 15 minutes and 36 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6210a8ab-ced7-4060-8c42-2f2bac51b414

📥 Commits

Reviewing files that changed from the base of the PR and between 9a65f7a and 36c629c.

⛔ Files ignored due to path filters (11)
  • lib/plugins/generated/CBand.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_13Through18_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1L_3Line.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ETA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_IN.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_OFF.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ON.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_ColonComma.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_StarPOS.ts is excluded by !**/generated/**
📒 Files selected for processing (66)
  • lib/MessageDecoder.ts
  • lib/plugins/escape_hatches/ARINC_702.ts
  • lib/plugins/escape_hatches/CBand.ts
  • lib/plugins/escape_hatches/Label_10_LDR.ts
  • lib/plugins/escape_hatches/Label_10_Slash.ts
  • lib/plugins/escape_hatches/Label_12_N_Space.ts
  • lib/plugins/escape_hatches/Label_12_POS.ts
  • lib/plugins/escape_hatches/Label_13Through18_Slash.ts
  • lib/plugins/escape_hatches/Label_15.ts
  • lib/plugins/escape_hatches/Label_15_FST.ts
  • lib/plugins/escape_hatches/Label_16_AUTPOS.ts
  • lib/plugins/escape_hatches/Label_16_Honeywell.ts
  • lib/plugins/escape_hatches/Label_16_N_Space.ts
  • lib/plugins/escape_hatches/Label_16_POSA1.ts
  • lib/plugins/escape_hatches/Label_16_TOD.ts
  • lib/plugins/escape_hatches/Label_1L_070.ts
  • lib/plugins/escape_hatches/Label_1L_3Line.ts
  • lib/plugins/escape_hatches/Label_1L_660.ts
  • lib/plugins/escape_hatches/Label_1L_Slash.ts
  • lib/plugins/escape_hatches/Label_1M_Slash.ts
  • lib/plugins/escape_hatches/Label_20_CFB01.ts
  • lib/plugins/escape_hatches/Label_20_POS.ts
  • lib/plugins/escape_hatches/Label_21_POS.ts
  • lib/plugins/escape_hatches/Label_22_OFF.ts
  • lib/plugins/escape_hatches/Label_22_POS.ts
  • lib/plugins/escape_hatches/Label_24_Slash.ts
  • lib/plugins/escape_hatches/Label_2P_FM3.ts
  • lib/plugins/escape_hatches/Label_2P_FM4.ts
  • lib/plugins/escape_hatches/Label_2P_FM5.ts
  • lib/plugins/escape_hatches/Label_30_Slash_EA.ts
  • lib/plugins/escape_hatches/Label_44_POS.ts
  • lib/plugins/escape_hatches/Label_44_Slash.ts
  • lib/plugins/escape_hatches/Label_4A.ts
  • lib/plugins/escape_hatches/Label_4A_01.ts
  • lib/plugins/escape_hatches/Label_4A_DIS.ts
  • lib/plugins/escape_hatches/Label_4A_DOOR.ts
  • lib/plugins/escape_hatches/Label_4A_Slash_01.ts
  • lib/plugins/escape_hatches/Label_4N.ts
  • lib/plugins/escape_hatches/Label_4T_AGFSR.ts
  • lib/plugins/escape_hatches/Label_4T_ETA.ts
  • lib/plugins/escape_hatches/Label_58.ts
  • lib/plugins/escape_hatches/Label_5Z_Slash.ts
  • lib/plugins/escape_hatches/Label_80.ts
  • lib/plugins/escape_hatches/Label_83.ts
  • lib/plugins/escape_hatches/Label_8E.ts
  • lib/plugins/escape_hatches/Label_B6_Forwardslash.ts
  • lib/plugins/escape_hatches/Label_ColonComma.ts
  • lib/plugins/escape_hatches/Label_H1_ATIS.ts
  • lib/plugins/escape_hatches/Label_H1_EZF.ts
  • lib/plugins/escape_hatches/Label_H1_FLR.ts
  • lib/plugins/escape_hatches/Label_H1_M_POS.ts
  • lib/plugins/escape_hatches/Label_H1_OFP.ts
  • lib/plugins/escape_hatches/Label_H1_OHMA.ts
  • lib/plugins/escape_hatches/Label_H1_Paren.ts
  • lib/plugins/escape_hatches/Label_H1_StarPOS.ts
  • lib/plugins/escape_hatches/Label_H1_WRN.ts
  • lib/plugins/escape_hatches/Label_H2_02E.ts
  • lib/plugins/escape_hatches/Label_HX.ts
  • lib/plugins/escape_hatches/Label_MA.ts
  • lib/plugins/escape_hatches/Label_QP.ts
  • lib/plugins/escape_hatches/Label_QQ.ts
  • lib/plugins/escape_hatches/Label_QR.ts
  • lib/plugins/escape_hatches/Label_QS.ts
  • lib/plugins/escape_hatches/Label_SQ.ts
  • lib/plugins/escape_hatches/index.ts
  • vendor/airframes-decoder

Walkthrough

Adds a vendored ADS decoder submodule, configures TypeScript path mappings, excludes vendor/generated code from lint/tests, adds npm scripts for ADS codegen, wires generated label plugins into the decoder, and adds a GitHub Actions workflow to validate generated artifacts.

Changes

ADS Decoder Submodule Integration

Layer / File(s) Summary
Submodule Registration and Update
.gitmodules, vendor/airframes-decoder
Git submodule vendor/airframes-decoder is registered and its commit pointer updated.
TypeScript Configuration for Vendored Code
tsconfig.json
Enables moduleResolution: "node", sets baseUrl, adds paths mappings for @airframes/ads-runtime-ts/*, and adds vendor to exclude.
Linter and Test Configuration
eslint.config.mts, jest.config.ts
ESLint ignores vendor/** and lib/plugins/generated/**; Jest maps @airframes/ads-runtime-ts imports to vendored runtime files and ignores node_modules/ and vendor/ for test discovery.
Code Generation Scripts
package.json
Adds ads:codegen-build, ads:generate, and ads:check npm scripts to build the vendored codegen tool, generate plugins into lib/plugins/generated, and verify generated artifacts are committed.
Decoder Plugin Generated Wiring
lib/MessageDecoder.ts, lib/plugins/escape_hatches/index.ts
Replaces several hand-written label plugins with generated equivalents and adds an escape_hatches placeholder export for future generated exports.
GitHub Actions Codegen Validation
.github/workflows/ads-check.yml
New workflow triggers on push/PR/manual to run a reusable ADS codegen-check workflow with TypeScript and repository paths configured.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 I hopped a patch into the tree,
Vendored wings for ADS to be,
Paths mapped, scripts hum, checks in flight,
Generated plugins take the night,
The warren's decoder now feels free.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: integrating the ADS submodule and wiring up codegen and runtime path aliases without behavioral changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dsl/adopt-v1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +11 to +16
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
with:
language: ts
generated-path: lib/plugins/generated
spec-path: vendor/airframes-decoder/spec
codegen-path: vendor/airframes-decoder/codegen

import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";

import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";

import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";
Comment thread lib/plugins/generated/Label_10_POS.ts Fixed

import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";
Comment thread lib/plugins/generated/Label_12_N_Space.ts Fixed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d7008546

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";
import * as hatches from "../escape_hatches";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Import the generated escape hatches from an existing module

When any generated plugin is type-checked or imported, this relative import resolves to lib/plugins/escape_hatches, but this commit does not add that module (a repo search for escape_hatches only finds these generated imports). The new generated tree is included by tsconfig.json, so consumers running a project type-check or later wiring these plugins into the decoder will hit a missing-module error before the generated plugins can be used.

Useful? React with 👍 / 👎.

Comment thread package.json
"test": "jest",
"ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build",
"ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated",
"ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run generation before diffing in ads:check

In a clean checkout where the ADS spec/submodule was changed but lib/plugins/generated was not regenerated, this command only checks for an existing uncommitted diff and exits successfully. That means npm run ads:check can pass with stale committed generated files, contrary to the script's stated purpose; it needs to run the generator (or invoke a check mode that does) before git diff --exit-code.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays the groundwork for adopting the shared “ADS” decoder spec/codegen by adding a vendored airframesio/acars-decoder submodule, wiring TypeScript path aliases to the vendored TS runtime, and committing the generated plugin sources so builds/tests don’t require running codegen.

Changes:

  • Add vendor/airframes-decoder as a git submodule and introduce TS path aliases for the ADS TS runtime.
  • Add npm scripts to build/run/check ADS codegen output and commit lib/plugins/generated/* to the repo.
  • Update ESLint/Jest config to ignore vendored and generated sources, and add a CI workflow to verify generated output is up-to-date.

Reviewed changes

Copilot reviewed 5 out of 75 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tsconfig.json Adds baseUrl/paths for ADS runtime and excludes vendor from compilation inputs.
package.json Adds ADS codegen build/generate/check scripts.
jest.config.ts Ignores tests under vendor/.
eslint.config.mts Ignores vendor/** and lib/plugins/generated/**.
.gitmodules Adds vendor/airframes-decoder submodule reference.
.github/workflows/ads-check.yml Adds CI job to verify generated tree matches the spec.
lib/plugins/generated/ARINC_702.ts Adds generated plugin wrapper.
lib/plugins/generated/CBand.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_10_LDR.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_10_POS.ts Adds generated plugin implementation.
lib/plugins/generated/Label_10_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_12_N_Space.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_12_POS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_13Through18_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_15.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_15_FST.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_16_AUTPOS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_16_Honeywell.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_16_N_Space.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_16_POSA1.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_16_TOD.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_1L_070.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_1L_3Line.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_1L_660.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_1L_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_1M_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_20_CFB01.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_20_POS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_21_POS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_22_OFF.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_22_POS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_24_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_2P_FM3.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_2P_FM4.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_2P_FM5.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_30_Slash_EA.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_44_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_44_POS.ts Adds generated plugin implementation.
lib/plugins/generated/Label_44_ON.ts Adds generated plugin implementation.
lib/plugins/generated/Label_44_OFF.ts Adds generated plugin implementation.
lib/plugins/generated/Label_44_IN.ts Adds generated plugin implementation.
lib/plugins/generated/Label_44_ETA.ts Adds generated plugin implementation.
lib/plugins/generated/Label_4A.ts Adds generated plugin implementation.
lib/plugins/generated/Label_4A_01.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4A_Slash_01.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4A_DOOR.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4A_DIS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4N.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4T_AGFSR.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_4T_ETA.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_58.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_5Z_Slash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_80.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_83.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_8E.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_B6_Forwardslash.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_ColonComma.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_ATIS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_EZF.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_FLR.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_M_POS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_OFP.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_OHMA.ts Adds generated plugin implementation.
lib/plugins/generated/Label_H1_Paren.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_StarPOS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H1_WRN.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_H2_02E.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_HX.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_MA.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_QP.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_QQ.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_QR.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_QS.ts Adds generated plugin wrapper.
lib/plugins/generated/Label_SQ.ts Adds generated plugin wrapper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
Comment on lines +19 to +21
"ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build",
"ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated",
"ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)"
Comment on lines +9 to +12
jobs:
ads-generated-up-to-date:
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
with:
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
package.json (1)

19-19: ⚡ Quick win

Prefer npm ci for reproducible codegen builds.

Using npm install may produce non-deterministic builds if package-lock.json is out of sync. Since this installs dependencies for the vendored codegen tool, npm ci will enforce the lockfile and fail fast if it's stale.

♻️ Proposed fix
-    "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build",
+    "ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm ci && npm run build",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 19, Replace the npm install call in the npm script
"ads:codegen-build" (which runs in vendor/airframes-decoder/codegen) with npm ci
so the vendored codegen build uses the lockfile for reproducible installs and
fails fast if the lockfile is stale; update the script invocation to run npm ci
&& npm run build instead of npm install && npm run build.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ads-check.yml:
- Around line 10-16: The workflow job ads-generated-up-to-date is missing an
explicit permissions block and currently inherits default GITHUB_TOKEN rights;
add a minimal permissions section to the workflow (at the top-level of the job
or workflow) granting only what the reusable workflow needs—e.g., permissions:
contents: read—so the codegen-check invocation (uses:
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) runs
with least privilege.
- Line 11: Update the reusable workflow reference used by the
ads-generated-up-to-date job (the line using
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) to
pin it to the specific commit SHA provided in the review and replace the branch
ref with that SHA; also add an explicit permissions: block (either at workflow
top or inside the ads-generated-up-to-date job) that scopes GITHUB_TOKEN to the
minimum required permissions for the codegen check so the workflow no longer
relies on default, broad token scopes.

In `@jest.config.ts`:
- Around line 162-165: The string literals in the Jest config's
testPathIgnorePatterns array use double quotes which conflicts with the
project's Prettier single-quote rule; update the array entries (the values
within testPathIgnorePatterns) to use single quotes (e.g., '/node_modules/' and
'/vendor/') so formatting/linting passes, leaving the rest of the
testPathIgnorePatterns property and its comments unchanged.

In `@tsconfig.json`:
- Line 5: tsconfig.json's compilerOptions.paths mapping for the alias
"`@airframes/ads-runtime-ts`" points to non-existent targets; update the paths
entry so each key under "compilerOptions.paths" for "`@airframes/ads-runtime-ts`"
(and any subpaths like "`@airframes/ads-runtime-ts/`*") points to the actual
TypeScript source file locations (for example the real index, helpers, and
escape_hatches files in the repo) instead of
"vendor/airframes-decoder/runtimes/typescript/index.ts",
"vendor/airframes-decoder/runtimes/typescript/helpers.ts", and
"vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"; locate
and replace those target strings in the tsconfig.json paths section so
TypeScript can resolve imports of `@airframes/ads-runtime-ts` correctly.

---

Nitpick comments:
In `@package.json`:
- Line 19: Replace the npm install call in the npm script "ads:codegen-build"
(which runs in vendor/airframes-decoder/codegen) with npm ci so the vendored
codegen build uses the lockfile for reproducible installs and fails fast if the
lockfile is stale; update the script invocation to run npm ci && npm run build
instead of npm install && npm run build.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7f552c64-d4d6-4287-bee0-24d3f64f2f3a

📥 Commits

Reviewing files that changed from the base of the PR and between 1748860 and c3d7008.

⛔ Files ignored due to path filters (68)
  • lib/plugins/generated/ARINC_702.ts is excluded by !**/generated/**
  • lib/plugins/generated/CBand.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_10_LDR.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_10_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_10_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_12_N_Space.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_12_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_13Through18_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_15.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_15_FST.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_16_AUTPOS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_16_Honeywell.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_16_N_Space.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_16_POSA1.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_16_TOD.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1L_070.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1L_3Line.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1L_660.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1L_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_1M_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_20_CFB01.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_20_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_21_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_22_OFF.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_22_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_24_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_2P_FM3.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_2P_FM4.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_2P_FM5.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_30_Slash_EA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ETA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_IN.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_OFF.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ON.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A_01.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A_DIS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A_DOOR.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4A_Slash_01.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4N.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4T_AGFSR.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_4T_ETA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_58.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_5Z_Slash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_80.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_83.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_8E.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_B6_Forwardslash.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_ColonComma.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_ATIS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_EZF.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_FLR.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_M_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_OFP.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_OHMA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_Paren.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_StarPOS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H1_WRN.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_H2_02E.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_HX.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_MA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_QP.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_QQ.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_QR.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_QS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_SQ.ts is excluded by !**/generated/**
📒 Files selected for processing (7)
  • .github/workflows/ads-check.yml
  • .gitmodules
  • eslint.config.mts
  • jest.config.ts
  • package.json
  • tsconfig.json
  • vendor/airframes-decoder

Comment on lines +10 to +16
ads-generated-up-to-date:
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
with:
language: ts
generated-path: lib/plugins/generated
spec-path: vendor/airframes-decoder/spec
codegen-path: vendor/airframes-decoder/codegen
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add an explicit permissions block.

The workflow inherits default GITHUB_TOKEN permissions, which may be broader than required. For a validation-only workflow that runs codegen checks, read-only access should suffice.

🛡️ Proposed fix to add minimal permissions
 jobs:
   ads-generated-up-to-date:
+    permissions:
+      contents: read
     uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1

Adjust permissions based on what the reusable workflow actually requires. If it only validates generated code, contents: read should be sufficient.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ads-generated-up-to-date:
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
with:
language: ts
generated-path: lib/plugins/generated
spec-path: vendor/airframes-decoder/spec
codegen-path: vendor/airframes-decoder/codegen
ads-generated-up-to-date:
permissions:
contents: read
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
with:
language: ts
generated-path: lib/plugins/generated
spec-path: vendor/airframes-decoder/spec
codegen-path: vendor/airframes-decoder/codegen
🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 11-16: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}

🪛 zizmor (1.25.2)

[warning] 10-17: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)


[error] 11-11: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ads-check.yml around lines 10 - 16, The workflow job
ads-generated-up-to-date is missing an explicit permissions block and currently
inherits default GITHUB_TOKEN rights; add a minimal permissions section to the
workflow (at the top-level of the job or workflow) granting only what the
reusable workflow needs—e.g., permissions: contents: read—so the codegen-check
invocation (uses:
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) runs
with least privilege.


jobs:
ads-generated-up-to-date:
uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the commit SHA for the init/ads-v1 branch
gh api repos/airframesio/acars-decoder/git/ref/heads/init/ads-v1 --jq '.object.sha'

Repository: airframesio/acars-decoder-typescript

Length of output: 121


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the workflow content around the referenced `uses:` line and top-level permissions
echo "=== File head (with line numbers) ==="
nl -ba .github/workflows/ads-check.yml | head -n 120

echo
echo "=== Grep for permissions/use blocks ==="
rg -n "^[[:space:]]*permissions:|^[[:space:]]*uses:" .github/workflows/ads-check.yml || true

Repository: airframesio/acars-decoder-typescript

Length of output: 179


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Confirm file exists ==="
ls -la .github/workflows/ads-check.yml

echo
echo "=== File head (with line numbers) ==="
cat -n .github/workflows/ads-check.yml | head -n 120

echo
echo "=== Grep for permissions/use blocks ==="
rg -n "^[[:space:]]*permissions:|^[[:space:]]*uses:" .github/workflows/ads-check.yml || true

echo
echo "=== Show lines around uses: (approx) ==="
# Show a reasonable window around the reported uses line
sed -n '1,80p' .github/workflows/ads-check.yml

Repository: airframesio/acars-decoder-typescript

Length of output: 1299


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== Full file ==="
cat -n .github/workflows/ads-check.yml

Repository: airframesio/acars-decoder-typescript

Length of output: 605


Pin the reusable workflow to a commit SHA.

.github/workflows/ads-check.yml (job ads-generated-up-to-date) currently calls codegen-check.yml via a branch ref (@init/ads-v1), which is a supply-chain risk. Pin it to the current commit for that ref:

uses: airframesio/acars-decoder/.github/workflows/codegen-check.yml@6da198f085a6ae56eb0291fe938c239aef8faa93

Also add an explicit permissions: block (workflow- or job-level) to scope GITHUB_TOKEN to the minimum required; this workflow currently has no permissions: configured.

🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 11-16: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{}}

🪛 zizmor (1.25.2)

[error] 11-11: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ads-check.yml at line 11, Update the reusable workflow
reference used by the ads-generated-up-to-date job (the line using
airframesio/acars-decoder/.github/workflows/codegen-check.yml@init/ads-v1) to
pin it to the specific commit SHA provided in the review and replace the branch
ref with that SHA; also add an explicit permissions: block (either at workflow
top or inside the ads-generated-up-to-date job) that scopes GITHUB_TOKEN to the
minimum required permissions for the codegen check so the workflow no longer
relies on default, broad token scopes.

Comment thread jest.config.ts
Comment on lines +162 to +165
testPathIgnorePatterns: [
"/node_modules/",
"/vendor/", // skip vendored airframes-decoder submodule's tests
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix quote style to match Prettier configuration.

The string literals use double quotes, but Prettier is configured to enforce single quotes. This will cause the build to fail or require a formatting pass.

🎨 Proposed fix
  testPathIgnorePatterns: [
-    "/node_modules/",
-    "/vendor/", // skip vendored airframes-decoder submodule's tests
+    '/node_modules/',
+    '/vendor/', // skip vendored airframes-decoder submodule's tests
  ],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
testPathIgnorePatterns: [
"/node_modules/",
"/vendor/", // skip vendored airframes-decoder submodule's tests
],
testPathIgnorePatterns: [
'/node_modules/',
'/vendor/', // skip vendored airframes-decoder submodule's tests
],
🧰 Tools
🪛 ESLint

[error] 163-163: Replace "/node_modules/" with '/node_modules/'

(prettier/prettier)


[error] 164-164: Replace "/vendor/" with '/vendor/'

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jest.config.ts` around lines 162 - 165, The string literals in the Jest
config's testPathIgnorePatterns array use double quotes which conflicts with the
project's Prettier single-quote rule; update the array entries (the values
within testPathIgnorePatterns) to use single quotes (e.g., '/node_modules/' and
'/vendor/') so formatting/linting passes, leaving the rest of the
testPathIgnorePatterns property and its comments unchanged.

Comment thread tsconfig.json
"compilerOptions": {
"target": "esNext",
"module": "commonjs",
"moduleResolution": "node",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that all TypeScript path mappings point to existing files

echo "Checking `@airframes/ads-runtime-ts` path mappings..."

files=(
  "vendor/airframes-decoder/runtimes/typescript/index.ts"
  "vendor/airframes-decoder/runtimes/typescript/helpers.ts"
  "vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"
)

missing=0
for file in "${files[@]}"; do
  if [[ -f "$file" ]]; then
    echo "$file"
  else
    echo "✗ MISSING: $file"
    missing=$((missing + 1))
  fi
done

if [[ $missing -eq 0 ]]; then
  echo "All path mappings verified."
else
  echo "ERROR: $missing file(s) missing."
  exit 1
fi

Repository: airframesio/acars-decoder-typescript

Length of output: 370


Fix tsconfig.json compilerOptions.paths targets for @airframes/ads-runtime-ts — the mappings point to missing files (vendor/airframes-decoder/runtimes/typescript/index.ts, helpers.ts, and escape_hatches/index.ts), so TypeScript will fail to resolve these aliases anywhere they’re imported.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tsconfig.json` at line 5, tsconfig.json's compilerOptions.paths mapping for
the alias "`@airframes/ads-runtime-ts`" points to non-existent targets; update the
paths entry so each key under "compilerOptions.paths" for
"`@airframes/ads-runtime-ts`" (and any subpaths like
"`@airframes/ads-runtime-ts/`*") points to the actual TypeScript source file
locations (for example the real index, helpers, and escape_hatches files in the
repo) instead of "vendor/airframes-decoder/runtimes/typescript/index.ts",
"vendor/airframes-decoder/runtimes/typescript/helpers.ts", and
"vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts"; locate
and replace those target strings in the tsconfig.json paths section so
TypeScript can resolve imports of `@airframes/ads-runtime-ts` correctly.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for wiring up the ADS submodule/codegen path. I think this needs another pass before merge because the generated tree is not currently reproducible or type-safe once exercised.

What I ran:

  • npm ci failed with an existing @typescript-eslint peer-resolution conflict, so I installed with npm ci --legacy-peer-deps to continue review.
  • npm run build passed.
  • npm test -- --runInBand passed.
  • npm run ads:codegen-build passed.
  • npm run ads:generate rewrote every generated file header from the author’s local absolute path to the checkout path, and npm run ads:check then failed.
  • npx tsc --noEmit fails; many failures are pre-existing test/source strictness issues, but the new lib/plugins/generated/** files also add errors such as missing ../escape_hatches, invalid ResultFormatter.fuel(...), and block-scoped variables used out of scope.

The current package build passes mostly because the generated files are not imported/exported yet. Since this PR is establishing the generated source and tooling foundation, I’d fix these now so the next PR does not inherit a generated tree that cannot be regenerated or imported cleanly.

Open in Web View Automation 

Sent by Cursor Automation: acars-decoder-typescript: PR Review

@@ -0,0 +1,40 @@
// AUTO-GENERATED from /Users/kevin/Cloud/Dropbox/work/airframes/acars-decoder-typescript/vendor/airframes-decoder/spec/labels/10/POS.yaml. Do not edit.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generated header embeds the author’s absolute local path. That makes the generated tree non-reproducible: after npm run ads:codegen-build && npm run ads:generate in this checkout, every generated file changed only from /Users/kevin/... to /workspace/..., and npm run ads:check then failed.

Please make the generator emit a stable path, usually repo-relative to the spec root (or omit the source path entirely), then regenerate and commit the stable output. Otherwise the new CI check will fail or create noise for every contributor whose checkout path differs.

import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";
import * as hatches from "../escape_hatches";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All generated plugins import ../escape_hatches, but this PR does not add lib/plugins/escape_hatches or otherwise make that relative module resolvable. A full type-check reports TS2307: Cannot find module '../escape_hatches' for each generated file.

Even plugins that do not call any hatch import it unconditionally, so this blocks importing any generated plugin. Either emit this import only when needed and point it at a real module, or add the local escape-hatch module with the functions the specs require.

Comment thread lib/plugins/generated/Label_44_POS.ts Outdated
ResultFormatter.timestamp(result, day);
ResultFormatter.timestamp(result, timestamp);
ResultFormatter.timestamp(result, eta);
ResultFormatter.fuel(result, fuel_in_tons);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generated code does not compile and would also be unsafe at runtime. fuel_in_tons is declared with const inside the if block above, but it is used here outside that block and may not exist for the ***/**** cases. The runtime ResultFormatter also exposes currentFuel(...)/burnedFuel(...), not fuel(...), so npx tsc --noEmit reports both Cannot find name 'fuel_in_tons' and Property 'fuel' does not exist.

The same pattern appears in the generated label 44 variants with fuel_remaining. This should be fixed in the spec/codegen/runtime contract before these generated plugins are committed as a usable baseline.

Comment thread package.json
"test": "jest",
"ads:codegen-build": "cd vendor/airframes-decoder/codegen && npm install && npm run build",
"ads:generate": "node vendor/airframes-decoder/codegen/dist/cli.js generate --target ts --spec vendor/airframes-decoder/spec --out lib/plugins/generated",
"ads:check": "git diff --exit-code -- lib/plugins/generated || (echo 'lib/plugins/generated is out of date. Run npm run ads:generate and commit.' && exit 1)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This freshness check only detects modifications to already-tracked generated files. If regeneration creates a new plugin file, git diff --exit-code -- lib/plugins/generated still exits successfully because untracked files are not part of git diff.

For a generated-code guard, prefer checking porcelain status for the path after generation, for example test -z "$(git status --porcelain -- lib/plugins/generated)", or combine git diff --exit-code with an explicit git ls-files --others --exclude-standard -- lib/plugins/generated check.

Comment thread tsconfig.json
"strict": true,
"baseUrl": ".",
"paths": {
"@airframes/ads-runtime-ts": ["vendor/airframes-decoder/runtimes/typescript/index.ts"],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compilerOptions.paths helps TypeScript resolve this alias during type-checking, but it does not by itself make the alias available to Jest/Babel or to Node for emitted JavaScript. Right now that is hidden because lib/plugins/generated/** is not imported by index.ts, so the package build never exercises these imports.

Before switching behavior to generated plugins, please add the matching runtime/test/build resolution path: for example a real workspace/package dependency for @airframes/ads-runtime-ts, Jest moduleNameMapper, and/or tsup alias/bundling configuration. Otherwise the first generated plugin import is likely to fail with Cannot find module '@airframes/ads-runtime-ts' outside the TypeScript compiler.

kevinelliott and others added 2 commits May 28, 2026 00:07
…oder

Proof point that the full vertical works end-to-end:

  spec/labels/10/POS.yaml
    → ads-gen --target ts
      → lib/plugins/generated/Label_10_POS.ts
        → @airframes/ads-runtime-ts {DecoderPlugin, ResultFormatter, helpers}
          → MessageDecoder dispatcher
            → 3/3 Label_10_POS tests + 407/407 full suite passes

Changes:

- Bump vendor/airframes-decoder submodule to e839bbc, which includes
  the emitter fix that suppresses raw auto-emit for fields consumed
  by a formatter (no more divergent raw.latitude/longitude/altitude
  next to the formatter's raw.position/altitude). Bytes now match
  the hand-written plugin.

- jest.config.ts: add moduleNameMapper for the @airframes/ads-runtime-ts
  path aliases (Jest doesn't read tsconfig paths by default).

- lib/plugins/escape_hatches/index.ts: placeholder so generated
  plugins' `import * as hatches from '../escape_hatches'` resolves
  (no hatches needed for Label_10_POS; later plugins populate this).

- lib/MessageDecoder.ts: import Label_10_POS from the generated tree
  and register it in place of the hand-written Plugins.Label_10_POS.

Verification:
  npm test -- --testPathPatterns=Label_10_POS  →  3/3 pass
  npm test                                      →  407/407 pass

Next: extend the pilot to the other declarative ports
(Label_44_IN/ON/OFF/ETA — also pure data, no escape hatches). The
remaining 60+ plugins need their escape-hatch implementations in
lib/plugins/escape_hatches/ before they can swap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…orts)

Extends the pilot to the remaining 4 fully-declarative spec ports
identified during the bulk-port phase. Same byte-for-byte parity proof
as Label_10_POS: no escape hatches needed, runtime helpers cover all
the decode-fn calls (coordinate_decimal_minutes, integer, float,
timestamp_hhmmss, airport).

Verification:
  npm test -- --testPathPatterns='Label_44_(IN|ON|OFF|ETA)'
    → 14/14 pass
  npm test
    → 407/407 pass (no regression)

All 5 of the v1 declarative ports now run through the generated tree.
The remaining ~60 plugins use whole-plugin escape hatches; their
behavioral swap waits on the corresponding hatch implementations under
lib/plugins/escape_hatches/, ported from the original TS plugin
sources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread lib/plugins/generated/Label_12_POS.ts Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@jest.config.ts`:
- Around line 91-98: Update the string literals in the moduleNameMapper object
to use single quotes to match Prettier settings: change the keys and mapped path
values inside moduleNameMapper (the "^`@airframes/ads-runtime-ts`$",
"^`@airframes/ads-runtime-ts/helpers`$",
"^`@airframes/ads-runtime-ts/escape_hatches`$" entries) from double-quoted to
single-quoted strings so linting/formatting passes.

In `@lib/MessageDecoder.ts`:
- Around line 14-18: lib/plugins/official.ts currently re-exports legacy
handwritten symbols (Label_10_POS, Label_44_ETA, Label_44_IN, Label_44_OFF,
Label_44_ON) which are unused except for generated imports like
Label_10_POS_Generated in lib/MessageDecoder.ts; either remove those legacy
export lines to eliminate dead/ambiguous API or explicitly deprecate them by
re-exporting with JSDoc `@deprecated` annotations and providing a migration note
pointing to the generated names (e.g., Label_10_POS -> Label_10_POS_Generated),
update any internal imports to use the generated symbols instead (verify
MessageDecoder.ts imports), and add a short changelog/migration comment so
consumers know to switch to the generated exports.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 46c233e5-edb4-4fad-baa1-c2b8b6adb4f8

📥 Commits

Reviewing files that changed from the base of the PR and between c3d7008 and 9a65f7a.

⛔ Files ignored due to path filters (6)
  • lib/plugins/generated/Label_10_POS.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ETA.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_IN.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_OFF.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_ON.ts is excluded by !**/generated/**
  • lib/plugins/generated/Label_44_POS.ts is excluded by !**/generated/**
📒 Files selected for processing (4)
  • jest.config.ts
  • lib/MessageDecoder.ts
  • lib/plugins/escape_hatches/index.ts
  • vendor/airframes-decoder
✅ Files skipped from review due to trivial changes (1)
  • lib/plugins/escape_hatches/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • vendor/airframes-decoder

Comment thread jest.config.ts
Comment on lines +91 to +98
moduleNameMapper: {
"^@airframes/ads-runtime-ts$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts",
"^@airframes/ads-runtime-ts/helpers$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts",
"^@airframes/ads-runtime-ts/escape_hatches$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts",
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix quote style to match Prettier configuration.

All string literals in moduleNameMapper use double quotes, but Prettier is configured to enforce single quotes. This will cause linting to fail.

🎨 Proposed fix
  moduleNameMapper: {
-    "^`@airframes/ads-runtime-ts`$":
-      "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts",
-    "^`@airframes/ads-runtime-ts/helpers`$":
-      "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts",
-    "^`@airframes/ads-runtime-ts/escape_hatches`$":
-      "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts",
+    '^`@airframes/ads-runtime-ts`$':
+      '<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts',
+    '^`@airframes/ads-runtime-ts/helpers`$':
+      '<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts',
+    '^`@airframes/ads-runtime-ts/escape_hatches`$':
+      '<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts',
  },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
moduleNameMapper: {
"^@airframes/ads-runtime-ts$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts",
"^@airframes/ads-runtime-ts/helpers$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts",
"^@airframes/ads-runtime-ts/escape_hatches$":
"<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts",
},
moduleNameMapper: {
'^`@airframes/ads-runtime-ts`$':
'<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts',
'^`@airframes/ads-runtime-ts/helpers`$':
'<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts',
'^`@airframes/ads-runtime-ts/escape_hatches`$':
'<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts',
},
🧰 Tools
🪛 ESLint

[error] 92-92: Replace "^@airframes/ads-runtime-ts$" with '^@airframes/ads-runtime-ts$'

(prettier/prettier)


[error] 93-93: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/index.ts'

(prettier/prettier)


[error] 94-94: Replace "^@airframes/ads-runtime-ts/helpers$" with '^@airframes/ads-runtime-ts/helpers$'

(prettier/prettier)


[error] 95-95: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/helpers.ts'

(prettier/prettier)


[error] 96-96: Replace "^@airframes/ads-runtime-ts/escape_hatches$" with '^@airframes/ads-runtime-ts/escape_hatches$'

(prettier/prettier)


[error] 97-97: Replace "<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts" with '<rootDir>/vendor/airframes-decoder/runtimes/typescript/escape_hatches/index.ts'

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@jest.config.ts` around lines 91 - 98, Update the string literals in the
moduleNameMapper object to use single quotes to match Prettier settings: change
the keys and mapped path values inside moduleNameMapper (the
"^`@airframes/ads-runtime-ts`$", "^`@airframes/ads-runtime-ts/helpers`$",
"^`@airframes/ads-runtime-ts/escape_hatches`$" entries) from double-quoted to
single-quoted strings so linting/formatting passes.

Comment thread lib/MessageDecoder.ts Outdated
… fixes)

Pulls in three fixes that unblock the Label_44_{IN,ON,OFF,ETA} pilot:

1. Emitter: when-gated field declarations are now hoisted (let X;
   outside the if), so downstream formatters see the variable
   (undefined when the guard fails) instead of crashing with
   ReferenceError. (80095f5)

2. Emitter: formatter type 'fuel' now maps to ResultFormatter.currentFuel
   (the actual runtime method name). Was emitting .fuel which threw
   'is not a function'. (ef58ee3)

3. Runtime: ResultFormatter.currentFuel tolerates undefined/NaN input
   so it can be called unconditionally from generated plugins even
   when the upstream when-gated value never got assigned. Matches the
   original hand-written guard pattern. (ce7d385)

Verified: 407/407 full suite passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

import { DecoderPlugin } from "@airframes/ads-runtime-ts";
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
Comment thread lib/plugins/generated/Label_12_N_Space.ts Fixed
Backed by ~60 escape-hatch implementations under lib/plugins/escape_hatches/
that port each hand-written plugin's decode() body into a free function
the generated wrapper invokes via 'import * as hatches from
../escape_hatches'. Implementations authored by 4 parallel agents in a
single pass.

What's now generated:
  CBand, ARINC_702, Label_ColonComma, Label_5Z_Slash,
  Label_10_LDR, Label_10_POS, Label_10_Slash, Label_12_N_Space,
  Label_12_POS, Label_13Through18_Slash, Label_15, Label_15_FST,
  Label_16_AUTPOS, Label_16_Honeywell, Label_16_N_Space, Label_16_POSA1,
  Label_16_TOD, Label_1L_3Line, Label_1L_070, Label_1L_660, Label_1L_Slash,
  Label_20_CFB01, Label_20_POS, Label_21_POS, Label_22_OFF, Label_22_POS,
  Label_24_Slash, Label_2P_FM3, Label_2P_FM4, Label_2P_FM5,
  Label_30_Slash_EA, Label_44_ETA, Label_44_IN, Label_44_OFF, Label_44_ON,
  Label_44_Slash, Label_4A_01, Label_4A_DIS, Label_4A_DOOR, Label_4A_Slash_01,
  Label_4N, Label_4T_AGFSR, Label_4T_ETA, Label_B6_Forwardslash, Label_H2_02E,
  Label_H1_ATIS, Label_H1_EZF, Label_H1_FLR, Label_H1_M_POS, Label_H1_OHMA,
  Label_H1_OFP, Label_H1_Paren, Label_H1_WRN, Label_H1_StarPOS, Label_HX,
  Label_58, Label_80, Label_83, Label_8E, Label_1M_Slash, Label_MA, Label_SQ,
  Label_QP, Label_QQ, Label_QR, Label_QS.

What's still hand-written (separate follow-up):
  - Plugins.Label_4A      — agent stubbed; variant-2/variant-3 field hatches
                            need design (formatter ownership of items list).
  - Plugins.Label_44_POS  — spec uses field-level customs
                            (parse_flight_level_or_ground +
                            flight_level_to_altitude_feet) not implemented
                            in this bulk pass.

Submodule bumped to airframes-decoder@c037de4 to pick up:
  - runtime: DecoderPlugin helpers made public (initResult/setDecodeLevel/
    failUnknown/debug) so escape hatches can delegate
  - runtime: re-export Arinc702Helper, FlightPlanUtils, RouteUtils,
    parseIcaoFpl, MIAMCoreUtils, base64ToUint8Array, inflateData,
    ascii85Decode from the package index
  - emitter: smart slugger handles camelCase boundaries (CBand→c-band,
    StarPOS→star-pos, 3Line→3-line, 4A stays 4a) so generated plugin
    names match the legacy ones byte-for-byte

Verified: 407/407 tests pass. No regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
import type { DecodeResult, Message, Options } from "@airframes/ads-runtime-ts";
import { ResultFormatter } from "@airframes/ads-runtime-ts";
import * as helpers from "@airframes/ads-runtime-ts/helpers";
import * as hatches from "../escape_hatches";
Two final swaps:

- Label_4A: spec changed (airframesio/acars-decoder@de6137f) from
  variants+field-customs to whole-plugin parse-custom. Hatch
  implementation in escape_hatches/Label_4A.ts mirrors the original
  decode() body byte-for-byte (3 variants by field count + first-char
  inspection, inline ResultFormatter calls).

- Label_44_POS: spec stays declarative; added the two field-level hatches
  it referenced — parse_flight_level_or_ground and
  flight_level_to_altitude_feet — in escape_hatches/Label_44_POS.ts.
  Both are 1-line ports of inline TS code:
    'GRD'/'***' → 0, else Number(value)
    multiply by 100

Submodule bumped to airframes-decoder@de6137f (carries the Label_4A spec
change).

Verified: 407/407 tests pass. End-to-end vertical for every TS plugin:
  spec/*.yaml → ads-gen → lib/plugins/generated/*.ts → escape_hatches/* →
  ResultFormatter / helpers → MessageDecoder dispatcher → original tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants