-
Notifications
You must be signed in to change notification settings - Fork 328
feat(audio): agent-ready foundation — contract layer, residency, discovery #2332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5e760a5
1833624
fbf865b
813b6bf
195f0c6
948166d
d446f25
26a2da8
3158004
89dde01
454ff92
54f655e
9db13eb
42c94a0
9a47a9a
bf69fbb
fcaa6ca
04a9ada
e3d457e
b26e5d3
38aeea0
3a2ba2f
e0e0839
0367061
5847683
b261c5d
be9118e
ccc23ed
e789524
0dad5b9
df1d8fd
0e9634a
b041038
c793f9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Audio stages — agent guardrails | ||
|
|
||
| These instructions apply to any AI coding agent working in `nemo_curator/stages/audio/`. | ||
| Codex and Cursor load this nested `AGENTS.md` automatically; Claude Code reaches it | ||
| through the sibling `CLAUDE.md` import. | ||
|
|
||
| Two different jobs happen in this directory, and they have opposite rules about editing. | ||
|
|
||
| ## If you are curating a dataset, this directory is read-only | ||
|
|
||
| Stage source is shared library code. Never change a stage, a threshold, a filter or | ||
| windowing logic to make one user's dataset produce the output they hoped for — diagnose | ||
| from the data instead. Inspect stage contracts through the public | ||
| `nemo_curator.stages.audio.agent` facade rather than reading stage source to answer what | ||
| a stage reads or writes: `agent.describe_stage("MyStage")` is the sanctioned answer, and | ||
| `agent.find_producers("role")` says which stages can produce a semantic role. | ||
|
|
||
| ## If you are authoring or fixing a stage, start here | ||
|
|
||
| Read `AGENT_READY.md` in this directory. It is the authoritative checklist and it is | ||
| maintained with the framework; work from it rather than from memory. | ||
|
|
||
| **Golden rule: every new knob defaults to today's behavior.** Agent-readiness is a | ||
| declaration layer over working code. If a change alters what an existing pipeline | ||
| produces, it is a behavior change and needs its own justification, not a checklist entry. | ||
|
|
||
| The mechanical contract is three things, each detailed in `AGENT_READY.md`: | ||
|
|
||
| 1. Inherit `AgentReady` and implement `describe()` returning a `StageContract` with | ||
| `reads`, `writes`, `cardinality` and honest `gates`. | ||
| 2. Make every `task.data` key you read or write a `*_key` constructor field — no bare key | ||
| literals in `process()`, or the key is invisible to the agent and cannot be remapped. | ||
| 3. Add `assert_agent_ready(MyStage(...), fixture_factory=...)` as a test. | ||
|
|
||
| Document what each externally consumed output means in the stage docstring and tests. | ||
| Roles prove that two stages can connect; clear semantic documentation lets reviewers | ||
| judge whether connecting them serves the user's intent. | ||
|
|
||
| Follow the repo's existing stage conventions while you do it: | ||
| `.cursor/rules/processing-stage-patterns.mdc` and | ||
| `.cursor/rules/composite-stage-patterns.mdc`. Those are upstream-maintained framework | ||
| rules — read them, never edit them. | ||
|
|
||
| Declare honestly even where it costs you: a stage that may drop rows is | ||
| `cardinality="filter"` even when dropping is incidental, and `gates` are environment facts | ||
| rather than aspirations. An optimistic contract is worse than a missing one, because the | ||
| planner treats it as ground truth. | ||
|
|
||
| ## Verify before you claim done | ||
|
|
||
| ```bash | ||
| .venv/bin/python -m pytest tests/stages/audio -m "not gpu" -q | ||
| .venv/bin/python -c 'from nemo_curator.stages.audio import agent; print(agent.describe_stage("MyStage").to_dict())' | ||
| ``` | ||
|
|
||
| If `describe` does not match what the code actually touches for those params, the contract | ||
| is wrong no matter what the tests say. |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @AGENTS.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,12 +33,17 @@ | |
| "AbbreviationConcatStage": "nemo_curator.stages.audio.text_filtering", | ||
| "AudioDataFilterStage": "nemo_curator.stages.audio.advanced_pipelines", | ||
| "BandFilterStage": "nemo_curator.stages.audio.filtering", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Add the class to both public-name tables and cover the top-level import.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, oversight. Added to both _LAZY and all, with the top-level import covered. |
||
| "ChannelCountStage": "nemo_curator.stages.audio.preprocessing", | ||
| "CreateInitialManifestAudioFolderStage": "nemo_curator.stages.audio.common", | ||
| "GetAudioDurationStage": "nemo_curator.stages.audio.common", | ||
| "ManifestCheckpointStage": "nemo_curator.stages.audio.common", | ||
| "ManifestReader": "nemo_curator.stages.audio.common", | ||
| "ManifestWriterStage": "nemo_curator.stages.audio.common", | ||
| "MonoConversionStage": "nemo_curator.stages.audio.preprocessing", | ||
| "PreserveByValueConditionsStage": "nemo_curator.stages.audio.common", | ||
| "PreserveByValueStage": "nemo_curator.stages.audio.common", | ||
| "RegexSubstitutionStage": "nemo_curator.stages.audio.text_filtering", | ||
| "SampleRateFilterStage": "nemo_curator.stages.audio.preprocessing", | ||
| "SIGMOSFilterStage": "nemo_curator.stages.audio.filtering", | ||
| "SegmentConcatenationStage": "nemo_curator.stages.audio.preprocessing", | ||
| "SpeakerSeparationStage": "nemo_curator.stages.audio.segmentation", | ||
|
|
@@ -54,13 +59,18 @@ | |
| "AbbreviationConcatStage", | ||
| "AudioDataFilterStage", | ||
| "BandFilterStage", | ||
| "ChannelCountStage", | ||
| "CreateInitialManifestAudioFolderStage", | ||
| "GetAudioDurationStage", | ||
| "ManifestCheckpointStage", | ||
| "ManifestReader", | ||
| "ManifestWriterStage", | ||
| "MonoConversionStage", | ||
| "PreserveByValueConditionsStage", | ||
| "PreserveByValueStage", | ||
| "RegexSubstitutionStage", | ||
| "SIGMOSFilterStage", | ||
| "SampleRateFilterStage", | ||
| "SegmentConcatenationStage", | ||
| "SpeakerSeparationStage", | ||
| "TimestampMapperStage", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Private foundation for agent-driven audio pipeline construction. | ||
|
|
||
| These modules are the STAGE-SIDE declaration layer: the vocabulary a stage uses | ||
| to describe itself (``StageContract``, ``Gates``, ``IOSpec``, the ``AgentReady`` | ||
| mixin, the shared role names) plus the discovery, planning and conformance code | ||
| that reads it. They live under ``stages/audio`` -- not under ``nemo_curator.audio_agent`` | ||
| -- on purpose: 43 stage modules import ``_agent_ready`` and 16 call into | ||
| ``_residency`` from inside ``process()``. Moving them into the agent package would | ||
| make ``nemo_curator.stages.audio`` unusable without the agent installed, inverting | ||
| a dependency that today points one way only. | ||
|
|
||
| Grouped into this subpackage purely so the stage tree reads as stages. Import the | ||
| public facade -- :mod:`nemo_curator.stages.audio.agent` -- rather than these | ||
| modules directly. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If any stage's
finalize()call raises, this loop stops immediately. Later stages then cannot publish their successful lifecycle state, and the Slurm shard completion manifest is skipped. For example, an ownership or file-identity error from one checkpoint can leave a later valid checkpoint without its_COMPLETEmarker. Each stage finalizer should be attempted before finalization errors are propagated.Knowledge Base Used: