Skip to content

feat(application): add 521 acoustic anomaly WASM operators - #871

Draft
Alain Uyidi (auyidi1) wants to merge 4 commits into
mainfrom
feat/521-acoustic-anomaly-operators
Draft

Alain Uyidi (auyidi1) wants to merge 4 commits into
mainfrom
feat/521-acoustic-anomaly-operators

Conversation

@auyidi1

@auyidi1 Alain Uyidi (auyidi1) commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request

Draft: must merge after #868 (517 sensor simulator) and #869 (518 MQTT predict adapter). The README links to both components and the operators follow their message contracts (517 acoustic readings; 518 request limits and response shape). The CI documentation link check passes; the relative 517 and 518 README links resolve only once those PRs merge. I'll update the branch and mark this ready then.

Description

Adds component 521 acoustic anomaly operators: two WASM map operators for AIO data flow graphs that detect acoustic anomalies with an autoencoder. The model runs outside the graph. Two data flow graphs are bridged over MQTT by the 518 predict adapter (#869), which calls a predictive endpoint such as a Foundry Local /v1/predict deployment.

audio ──► [acoustic-featurize] ──► predict/v1/acoustic-anomaly/model/{model}/request ──► 518 adapter ──► model
verdict ◄── [acoustic-threshold] ◄── predict/v1/acoustic-anomaly/model/{model}/response ◄──┘
  • featurize-acoustic:
    • Turns {sample_rate, samples} into 640-dimensional log-mel rows, following the DCASE 2020 Task 2 autoencoder baseline: power STFT (n_fft 1024, hop 512, periodic Hann window, centered reflect padding as in the baseline's librosa 0.6), 128 Slaney mel bands, 10*log10(power + eps), and 5 frames concatenated frame-major. Models must be trained and calibrated with the same padding.
    • Emits the adapter request {"inputs": [...], "context": {...}} with compact f32 rows (about 7 KB each), copying configured identity fields such as asset_id into context so the verdict can identify its source.
    • Validates the sample rate (8 to 192 kHz, optionally pinned with expected_sample_rate), samples (finite, in [-1, 1], 2048 up to max_samples), the serialized context against 518's 1 KiB limit, and the request size against max_request_bytes (default 1 MiB, 518's MAX_REQUEST_BYTES default). Only the first max_batch_size windows are computed; the rest are counted as dropped.
  • threshold-anomaly:
    • Reads the score from one configured score_field (default score, matching 518's response example and mock model) in the adapter response outputs: a number, per-window numbers, or single-value rows. It never searches for other numbers.
    • Aggregates with an overflow-safe mean or max and compares against a required threshold that has no default.
    • Emits a verdict with the context. Adapter errors and malformed results become error verdicts (BACKEND_TIMEOUT, INVALID_RESULT, and so on), so failures stay visible.
  • Graph definitions: graph-featurize-acoustic.yaml and graph-threshold-anomaly.yaml validate against the aio-wasm-graph-config-1.0.0 schema.
  • Blueprint example: blueprints/full-multi-node-cluster/terraform/dataflow-graphs-acoustic-anomaly.tfvars.example wires both graphs (requires should_include_acr_registry_endpoint = true) and sets the CloudEvents type and source headers on each destination while keeping id and traceparent.
  • Scripts: scripts/build-wasm.sh and scripts/push-to-acr.sh follow the 515 pattern (clippy, host tests, optional audit, release build; push refuses to overwrite by default and records an audit log). They also handle the underscore .wasm file name of hyphenated crates.

Related Issue

Part of the custom workload messaging work tracked in #835 and published in #852. Depends on #868 and #869.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Blueprint modification or addition
  • Component modification or addition
  • Documentation update
  • CI/CD pipeline change
  • Other (please describe):

Implementation Details

  • Both crates follow the 515 template: wasm_graph_sdk =1.1.3 from the AIO SDK feed, wit-bindgen 0.22, serde_json with alloc, and the same clippy lint levels and release profile. featurize-acoustic adds rustfft 6.
  • Pure functions (build_request, wav_to_features, build_verdict, and others) never call the SDK logger, which panics on the host target. Logging and metrics happen only in the operator entry points, so all logic is unit-testable with cargo test on the host.
  • The log floor is f64::EPSILON cast to f32, which matches the reference's sys.float_info.epsilon, so silent bins equal the reference.
  • Registered in codecov.yml ignore like the other WASM components, the rust-analyzer linkedProjects in .vscode/settings.json, the application index, and .cspell/general-technical.txt. .nobuild excludes the component from the container pipeline.

Testing Performed

  • Terraform plan/apply
  • Blueprint deployment test
  • Unit tests
  • Integration tests
  • Bug fix includes regression test (see Test Policy)
  • Manual validation
  • Other: librosa parity, schema validation, and Terraform variable validation
  • scripts/build-wasm.sh passes end to end: clippy with -D warnings on the WASM target, host tests (20 for featurize-acoustic, 8 for threshold-anomaly), cargo-audit, and release builds (300 KB and 136 KB). cargo fmt --check passes.
  • librosa parity: a deterministic signal (440 Hz plus 3200 Hz plus LCG noise) matches librosa 0.11.0 with pad_mode="reflect" within 0.05 dB on 14 sampled values and the mean of every window. The fixture and its generator script are included.
  • Tests also cover truncation (the first max_batch_size windows equal those of the full clip), request and context size limits measured as 518 measures them, and 518's exact success and error response shapes.
  • Cross-component contract, with real outputs at every hop:
    1. A 517 simulator acoustic reading (4096 samples, asset pump-07) went through featurize-acoustic, producing 5 x 640 rows with context {asset_id: pump-07, ...}.
    2. That was published to the 518 adapter backed by its mock model, which returned success with the context echoed.
    3. The response went through threshold-anomaly, producing a verdict with anomaly, score, windows, and the original context.
    4. The error path was also exercised: the adapter's BACKEND_UNAVAILABLE became an error verdict that kept the context.
  • Both graph definitions validate against https://www.schemastore.org/aio-wasm-graph-config-1.0.0.json.
  • The tfvars example passes terraform fmt -check, and the full-multi-node-cluster blueprint passes terraform validate; the example's dataflow_graphs (including headers) type-checks against the blueprint variable via terraform console (Terraform 1.16.5).
  • Validate-RustCrateRegistration.ps1 passes (19 crates). shellcheck, ruff, and yamllint (warnings only, matching existing graph files) pass. Grype finds no vulnerabilities in either lock file. gitleaks finds no leaks. markdownlint, markdown-table-formatter, cspell, and frontmatter validation pass. The CI documentation link check passes; a local markdown-link-check of this README flags only the relative 517 and 518 links, which resolve once feat(application): add 517 synthetic sensor simulator and chart #868 and feat(application): add 518 MQTT predict adapter for HTTP model endpoints #869 merge.

Validation Steps

  1. cd src/500-application/521-acoustic-anomaly-operators && ./scripts/build-wasm.sh (requires the wasm32-wasip2 target)
  2. Review the graph definitions under resources/graphs/ and the README deployment example.

Checklist

  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have run terraform fmt on all Terraform code
  • I have run terraform validate on all Terraform code
  • I have run az bicep format on all Bicep code
  • I have run az bicep build to validate all Bicep code
  • I have checked for any sensitive data/tokens that should not be committed
  • Lint checks pass (run applicable linters for changed file types)

Security Review

  • No credentials, secrets, or tokens are hardcoded or logged
  • RBAC and identity changes follow least-privilege principles
  • No new network exposure or public endpoints introduced without justification
  • Dependency additions or updates have been reviewed for known vulnerabilities
  • Container image changes use pinned digests or SHA references

Additional Notes

- featurize-acoustic: DCASE-style log-mel rows as predict adapter requests
- threshold-anomaly: score adapter responses against a required threshold
- librosa 0.11 parity fixture and generator script
- two graph definitions bridged by the 518 MQTT predict adapter
- register in codecov ignore, VS Code, spelling, and application index

🎧 - Generated by Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

📚 Documentation Health Report

Generated on: 2026-10-08 18:19:47 UTC

📈 Documentation Statistics

Category File Count
Main Documentation 224
Infrastructure Components 234
Blueprints 40
GitHub Resources 26
AI Assistant Guides (Copilot) 17
Total 541

🏗️ Three-Tree Architecture Status

  • ✅ Bicep Documentation Tree: Auto-generated navigation
  • ✅ Terraform Documentation Tree: Auto-generated navigation
  • ✅ README Documentation Tree: Manual README organization

🔍 Quality Metrics

  • Frontmatter Validation:
    success
  • Link Validation: success

This report is automatically generated by the Documentation Automation workflow.

🎨 - Generated by Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

📚 Documentation Health Report

Generated on: 2026-10-08 18:36:44 UTC

📈 Documentation Statistics

Category File Count
Main Documentation 224
Infrastructure Components 234
Blueprints 40
GitHub Resources 26
AI Assistant Guides (Copilot) 17
Total 541

🏗️ Three-Tree Architecture Status

  • ✅ Bicep Documentation Tree: Auto-generated navigation
  • ✅ Terraform Documentation Tree: Auto-generated navigation
  • ✅ README Documentation Tree: Manual README organization

🔍 Quality Metrics

  • Frontmatter Validation:
    success
  • Link Validation: success

This report is automatically generated by the Documentation Automation workflow.

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 42.15%. Comparing base (eadd35c) to head (db3bd29).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #871   +/-   ##
=======================================
  Coverage   42.15%   42.15%           
=======================================
  Files          42       42           
  Lines        7334     7334           
=======================================
  Hits         3092     3092           
  Misses       4242     4242           
Flag Coverage Δ
rust 42.15% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Alain Uyidi (auyidi1) and others added 2 commits October 8, 2026 13:37
- use reflect STFT padding and regenerate the librosa fixture
- serialize compact f32 rows; cap request and context bytes
- featurize only the forwarded windows; add expected_sample_rate
- default score_field to score; overflow-safe mean
- test against the 518 predict adapter response shape

🔧 - Generated by Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- add full-multi-node-cluster acoustic anomaly tfvars example
- set CloudEvents type and source headers on graph destinations
- document reflect padding, request and context limits, 517 ranges
- add prerequisites section

📝 - Generated by Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

📚 Documentation Health Report

Generated on: 2026-10-08 20:41:43 UTC

📈 Documentation Statistics

Category File Count
Main Documentation 224
Infrastructure Components 234
Blueprints 40
GitHub Resources 26
AI Assistant Guides (Copilot) 17
Total 541

🏗️ Three-Tree Architecture Status

  • ✅ Bicep Documentation Tree: Auto-generated navigation
  • ✅ Terraform Documentation Tree: Auto-generated navigation
  • ✅ README Documentation Tree: Manual README organization

🔍 Quality Metrics

  • Frontmatter Validation:
    success
  • Link Validation: success

This report is automatically generated by the Documentation Automation workflow.

This branch has not been deployed

No deployments
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.

2 participants