> This page is for version Main (default).
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo/gym/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo/gym/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo/gym/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo/gym/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo/gym/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo/gym/v0.3.0/llms.txt
> - 0.2.1: https://docs.nvidia.com/nemo/gym/v0.2.1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/gym/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/gym/_mcp/server.

# nemo_gym.data.tasks.harbor.manifest

`manifest.toml`: the derived identity of a dataset folder.

The file sits beside the task folders and holds only facts computed from them: where the folders
came from (`source`), one dataset digest, the digest of `dataset.toml` alone, and per task the
folder digest (the value rows carry as
`_ng_digest`) with its upstream pin. The dataset's name and version live only in `dataset.toml`, so nothing
appears in both files; what a fetch records besides is the hub reference it was made from (`ref`), a fact of the
fetch like the pins, which is what a committed entry's declared `source` is checked against without the hub
(`nemo_gym.data.tasks.harbor.prepare._check_fetch_record`). Nobody edits the manifest by hand.

The output is deterministic: a fixed key order, sorted tasks and no timestamps, so equal manifests
mean identical inputs and two runs compare by `[dataset].digest`. The dataset digest is a hash over
the sorted per-task digests, then the `dataset.toml` digest, then, when the
dataset ships them, the digest of the dataset-level Gym files that shape every task (`task_data.py`, the
row model, and `verifier.py`, the shared grader; `dataset_files_digest`, recorded only when present, so a
dataset without them hashes and reads as before). Two datasets that differ only in a timeout override in
`dataset.toml`, or only in the shared grader, are therefore different datasets, on purpose: either can
change a score. Like `dataset.toml`, those files are Gym's layer, not fetched content: an edit rewrites the
manifest and is reported, while an edited task folder of a fetched dataset is refused.

Fetchers write the manifest (`nemo_gym.data.tasks.harbor.hub`, `nemo_gym.data.tasks.harbor.package_store`)
and record only the tasks they fetched, so a folder nobody fetched is never blessed; prepare writes it for a
local folder, unless git tracks the folder (the repository's own example datasets), whose identity is
computed in memory. Prepare recomputes the per-task digests from the folders and refuses to run a fetched
dataset whose folders no longer match (`check_manifest`). A task folder that cannot be hashed (a file
under it escapes it through a link, or cannot be read) is recorded by name without a digest and does not
enter the dataset digest: the loader refuses the same folder, so no row runs it, and the rest of a local
dataset still prepares; a fetched manifest that recorded its digest names it when it refuses.

## Module Contents

### Classes

| Name                                                                                        | Description                                                                          |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [`Manifest`](#nemo_gym-data-tasks-harbor-manifest-Manifest)                                 | `manifest.toml` in memory. `tasks` maps a task name to its `digest` and pin keys.    |
| [`ManifestError`](#nemo_gym-data-tasks-harbor-manifest-ManifestError)                       | The manifest cannot be read, or the task folders no longer match it.                 |
| [`UnsupportedManifestError`](#nemo_gym-data-tasks-harbor-manifest-UnsupportedManifestError) | The manifest was written by a newer Gym (a `schema_version` this Gym does not read). |

### Functions

| Name                                                                                | Description                                                                                                  |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| [`_file_digest`](#nemo_gym-data-tasks-harbor-manifest-_file_digest)                 | -                                                                                                            |
| [`_quote`](#nemo_gym-data-tasks-harbor-manifest-_quote)                             | `value` as a TOML basic string, ASCII only.                                                                  |
| [`_some`](#nemo_gym-data-tasks-harbor-manifest-_some)                               | The first five of `names` and how many there are in all.                                                     |
| [`_write_or_warn`](#nemo_gym-data-tasks-harbor-manifest-_write_or_warn)             | Write the manifest; a folder that cannot be written (read-only shared storage) keeps its in-memory identity. |
| [`check_manifest`](#nemo_gym-data-tasks-harbor-manifest-check_manifest)             | Recompute the manifest of `folder` from disk and reconcile it with the one on disk.                          |
| [`check_task_manifest`](#nemo_gym-data-tasks-harbor-manifest-check_task_manifest)   | Hold one task folder to the manifest of the dataset folder whose check reaches it, when that is a fetch's.   |
| [`dataset_digest`](#nemo_gym-data-tasks-harbor-manifest-dataset_digest)             | The dataset's identity: sorted per-task digests, then `dataset.toml`, then the dataset-level files when      |
| [`dataset_files_digest`](#nemo_gym-data-tasks-harbor-manifest-dataset_files_digest) | Digest of the dataset-level Gym files that shape tasks (`DATASET_FILES`): name and content of each one       |
| [`dataset_toml_digest`](#nemo_gym-data-tasks-harbor-manifest-dataset_toml_digest)   | Digest of `dataset.toml` alone, or of nothing when the file is absent.                                       |
| [`enclosing_manifest`](#nemo_gym-data-tasks-harbor-manifest-enclosing_manifest)     | The nearest fetched manifest above `path` whose dataset folder's check reaches `path`, with its folder.      |
| [`gym_layer_change`](#nemo_gym-data-tasks-harbor-manifest-gym_layer_change)         | Which part of the Gym layer differs between two manifests of one task set, for a rewrite notice.             |
| [`refresh_gym_layer`](#nemo_gym-data-tasks-harbor-manifest-refresh_gym_layer)       | Bring a fetched manifest's Gym-layer digests up to date with `folder` without touching its task records.     |
| [`report_rewrite`](#nemo_gym-data-tasks-harbor-manifest-report_rewrite)             | The one-line notice that `folder`'s manifest was rewritten, and how the dataset digest moved.                |
| [`task_differences`](#nemo_gym-data-tasks-harbor-manifest-task_differences)         | One line naming the tasks whose digest differs between a manifest and the folders, or `None`.                |
| [`task_folders`](#nemo_gym-data-tasks-harbor-manifest-task_folders)                 | The task folders under `folder`, as the loader discovers them (`iter_task_folders`: recursively,             |
| [`tracked_by_git`](#nemo_gym-data-tasks-harbor-manifest-tracked_by_git)             | Whether git tracks files under `folder`: the repository's own example datasets, or a checkout.               |

### Data

[`DATASET_FILES`](#nemo_gym-data-tasks-harbor-manifest-DATASET_FILES)

[`DIGEST_RECORDING_SOURCES`](#nemo_gym-data-tasks-harbor-manifest-DIGEST_RECORDING_SOURCES)

[`LOCAL_SOURCE`](#nemo_gym-data-tasks-harbor-manifest-LOCAL_SOURCE)

[`MANIFEST_FILE`](#nemo_gym-data-tasks-harbor-manifest-MANIFEST_FILE)

[`MANIFEST_SCHEMA_VERSION`](#nemo_gym-data-tasks-harbor-manifest-MANIFEST_SCHEMA_VERSION)

[`SOURCES`](#nemo_gym-data-tasks-harbor-manifest-SOURCES)

[`TASK_FILE`](#nemo_gym-data-tasks-harbor-manifest-TASK_FILE)

[`TASK_KEYS`](#nemo_gym-data-tasks-harbor-manifest-TASK_KEYS)

[`_EMPTY_DIGEST`](#nemo_gym-data-tasks-harbor-manifest-_EMPTY_DIGEST)

[`_NO_HARD_LINKS`](#nemo_gym-data-tasks-harbor-manifest-_NO_HARD_LINKS)

[`_SURROGATE_PAIR`](#nemo_gym-data-tasks-harbor-manifest-_SURROGATE_PAIR)

[`logger`](#nemo_gym-data-tasks-harbor-manifest-logger)

### API

```python
class nemo_gym.data.tasks.harbor.manifest.Manifest(
    source: str,
    digest: str,
    dataset_toml_digest: str,
    tasks: dict[str, dict[str, str]] = dict(),
    dataset_files_digest: str = _EMPTY_DIGEST,
    ref: str | None = None,
    unhashable: frozenset[str] = frozenset()
)
```

Dataclass

`manifest.toml` in memory. `tasks` maps a task name to its `digest` and pin keys.

**`dataset_files_digest`** `str = _EMPTY_DIGEST`

---

**`dataset_toml_digest`** `str`

---

**`digest`** `str`

---

**`pins`** `dict[str, dict[str, str]]`

The per-task entries without their digests: the upstream pins alone.

---

**`records_content`** `bool`

Whether the manifest records what the task folders held, so a pin without a digest is unfinished business.

One with a dataset digest does, and so does one written before the dataset digest existed by a fetcher
that recorded a digest per landed task from the start (`DIGEST_RECORDING_SOURCES`), whether or not
a task had landed when it was written; a registry manifest from before digests has pins only, and
`check_manifest` upgrades it by hashing the folders it finds.

---

**`ref`** `str | None = None`

---

**`source`** `str`

---

**`task_digests`** `dict[str, str | None]`

Per-task folder digests; `None` for a task pinned before its folder was written or one that cannot be hashed.

---

**`tasks`** `dict[str, dict[str, str]] = field(default_factory=dict)`

---

**`unhashable`** `frozenset[str] = field(default_factory=frozenset)`

---

```python
nemo_gym.data.tasks.harbor.manifest.Manifest._write_text(
    fd: int
) -> None
```

Write the file's bytes to `fd` and flush them to disk; the descriptor is closed.

```python
nemo_gym.data.tasks.harbor.manifest.Manifest.build(
    folder: pathlib.Path,
    source: str,
    pins: dict[str, dict[str, str]] | None = None,
    digests: dict[str, str] | None = None,
    names: collections.abc.Iterable[str] | None = None,
    ref: str | None = None
) -> nemo_gym.data.tasks.harbor.manifest.Manifest
```

classmethod

Compute the manifest of `folder` from its task folders and `dataset.toml`.

`pins` are the upstream pins to record per task; a pinned task whose folder is absent
(an interrupted fetch) keeps its pin and gets no digest. `digests` are folder digests
already computed (by a loader or a fetch); any task folder not in it is hashed here, and the
mapping is extended in place so a caller can reuse the work. `ref` is the hub reference a fetch
was made from, recorded as the pins are and kept by every rewrite of the manifest.

`names` are the tasks to record. A fetcher passes the tasks it fetched, so a folder it did not
fetch stays unrecorded (and prepare refuses it as not in the manifest) and no folder is scanned
or stat-ed again for a name whose digest is known. Without it, every task folder on disk is
recorded: a local dataset, or prepare recomputing a fetched one to compare. A folder found there
that cannot be hashed is recorded by name with no digest (`unhashable`) and left out of the dataset
digest, with a warning; the loader refuses it per task, so the rest of the dataset still prepares.

```python
nemo_gym.data.tasks.harbor.manifest.Manifest.read(
    folder: pathlib.Path
) -> nemo_gym.data.tasks.harbor.manifest.Manifest | None
```

classmethod

The manifest beside the task folders, `None` when there is none; malformed raises.

```python
nemo_gym.data.tasks.harbor.manifest.Manifest.text() -> str
```

The file's bytes: fixed key order, sorted tasks, no timestamps.

```python
nemo_gym.data.tasks.harbor.manifest.Manifest.write(
    folder: pathlib.Path,
    exclusive: bool = False
) -> pathlib.Path
```

Write `manifest.toml` atomically: a failed write leaves the previous, truthful file intact.

The file keeps the permissions it had, so a shared dataset another user could read stays
readable after a rewrite; a new manifest gets the usual umask-aware mode (`0o666` before
the umask, like `Path.write_text`), not the owner-only mode a `mkstemp` file would have.

With `exclusive`, the manifest is created only where none is and `FileExistsError` is
raised otherwise, the target untouched (the temporary is written and removed either way): the
complete file is linked into place, so of two writers racing for an empty folder exactly one
succeeds and a reader never sees a partial file. A filesystem without hard links falls back to
an exclusive create of the target itself, still one winner, though a reader may then glimpse
the file before its last byte. A fetcher claims a folder this way before its first task lands.

```python
class nemo_gym.data.tasks.harbor.manifest.ManifestError()
```

**Bases:** `ValueError`

The manifest cannot be read, or the task folders no longer match it.

```python
class nemo_gym.data.tasks.harbor.manifest.UnsupportedManifestError()
```

**Bases:** [ManifestError](#nemo_gym-data-tasks-harbor-manifest-ManifestError)

The manifest was written by a newer Gym (a `schema_version` this Gym does not read).

Distinct from a malformed manifest: the file is intact and says more than this Gym understands,
so a fetcher must leave it alone rather than rewrite it with what it knows.

```python
nemo_gym.data.tasks.harbor.manifest._file_digest(
    path: pathlib.Path
) -> str
```

```python
nemo_gym.data.tasks.harbor.manifest._quote(
    value: str
) -> str
```

`value` as a TOML basic string, ASCII only.

JSON string escapes are valid TOML basic-string escapes (the quote, the backslash, the controls and
U+007F as `\u007f`, other non-ASCII as `\uXXXX`) except that JSON writes a character above U+FFFF
as a UTF-16 surrogate pair, which TOML forbids; that pair becomes TOML's `\UXXXXXXXX`.

```python
nemo_gym.data.tasks.harbor.manifest._some(
    names: list[str]
) -> str
```

The first five of `names` and how many there are in all.

```python
nemo_gym.data.tasks.harbor.manifest._write_or_warn(
    manifest: nemo_gym.data.tasks.harbor.manifest.Manifest,
    folder: pathlib.Path
) -> bool
```

Write the manifest; a folder that cannot be written (read-only shared storage) keeps its in-memory identity.

```python
nemo_gym.data.tasks.harbor.manifest.check_manifest(
    folder: pathlib.Path,
    digests: dict[str, str] | None = None
) -> nemo_gym.data.tasks.harbor.manifest.Manifest
```

Recompute the manifest of `folder` from disk and reconcile it with the one on disk.

* No manifest: the folder is a local dataset; one is written with source `local`, unless git
  tracks the folder, whose identity is then computed in memory and nothing written.
* A manifest naming a source this Gym does not know (written by a newer Gym, or edited): refused,
  never read as local, because this Gym cannot tell whether the folders still match it.
* A manifest without digests (written before they existed): upgraded in place, pins kept.
* A manifest with per-task digests but no dataset digest (the package-store format before the schema
  was numbered): the folders are held to the recorded digests, and an unchanged folder is upgraded in
  place, the recorded digests kept, so a cache written by an earlier Gym keeps its fetch record.
* A fetched manifest pinning a task with no digest: the fetch that wrote it was interrupted
  before that task landed (a fetcher claims the folder with every pin before its first download),
  so the folder is refused, named with the tasks still to come, until the fetch is run again.
* Task folders differ from a `local` manifest: the folder is its own source of truth, so the
  manifest is rewritten and the new digest reported.
* No manifest, or a `local` one, in a folder that a fetched dataset's check reaches (a subfolder of a
  fetched dataset, within its discovery range, see `enclosing_manifest`): refused, and no local manifest
  written there. The task folders under it are that dataset's, recorded in its manifest and held to it by its
  check and by `check_task_manifest`; a local manifest beside them would prepare an edited one as
  `local` and shadow the fetched manifest for the single-task check.
* Task folders differ from a fetched manifest: the folder was edited by hand, or its source
  moved since the fetch. `ManifestError` says which tasks and what to do.
* Only `dataset.toml` or a dataset-level `task_data.py` / `verifier.py` moved: the Gym
  layer changed on purpose, the task folders are the same, so the derived facts are rewritten without a fetch,
  and the rewrite says which.

`digests` are folder digests a loader already computed, extended in place with the rest.
Returns the manifest now on disk.

```python
nemo_gym.data.tasks.harbor.manifest.check_task_manifest(
    task: pathlib.Path,
    digests: dict[str, str] | None = None
) -> nemo_gym.data.tasks.harbor.manifest.Manifest | None
```

Hold one task folder to the manifest of the dataset folder whose check reaches it, when that is a fetch's.

A single task folder target (`<dataset>/<task>`, or a task deeper under the dataset folder) is prepared with
the `dataset.toml` and image records beside it but is no folder of task folders, so `check_manifest`
never runs for it; without this check an edited task of a fetched dataset prepared alone, as `local`, while
the dataset folder was refused. The manifest that holds the task is the one the dataset folder's check holds it
to, not only its parent's: that check discovers tasks under subfolders too (`iter_task_folders`, at most
`MAX_DISCOVERY_DEPTH` levels down, never inside a hidden folder or through a link) and names each by its
folder name, so a task moved into a subfolder of a fetched dataset is still the task its manifest records and
is held to it here, while a task that check never sees (hidden, deeper, under a hidden or linked folder, or inside
another task folder, as a fixture a task ships) is held to nothing, and a manifest above that range is not read
(`enclosing_manifest`; a folder in between
that carries a fetched manifest of its own, such as a dataset fetched inside another folder, holds its tasks
itself, and a `local` one in between is passed over, as is a `manifest.toml` this Gym cannot read as a
fetch's record, another tool's for one). The task's own parent is read as it was: it is the dataset root the
task is prepared with, so its manifest is the task's dataset's whatever it says, and one naming a source this
Gym does not know, or written by a newer Gym, refuses the task as it refuses the dataset folder. The task's
folder digest is compared with the one that manifest
records for it, with `task_differences`' words: a folder that differs was edited by hand or its source
moved, one the manifest does not record was never fetched, one that cannot be hashed is refused as the dataset
folder's check refuses it, and one recorded without a digest is a fetch that never finished. Nothing is
written: the manifest stays the dataset folder's record, and it is not upgraded or rewritten here. Returns that
manifest, for the task's identity to carry its source (the task is still prepared with the `dataset.toml` and
image records beside it, as any single task folder target is: the manifest holds its content, not the settings
the preparation applies), or `None` when no fetched manifest in that range holds the task (a standalone task
folder, whose parent is whatever directory holds it, or one whose nearest manifest is `local`: the folder is
its own source of truth, and the dataset folder's next prepare records the edit) or that manifest is from
before digests were recorded (pins only; the dataset folder's prepare upgrades it).

`digests` are folder digests already computed, keyed by task name as `check_manifest` keys them: the
task's is used when present (a loader's, to check the folder as it loaded) and hashed and stored otherwise.

```python
nemo_gym.data.tasks.harbor.manifest.dataset_digest(
    task_digests: dict[str, str],
    dataset_toml: str,
    dataset_files: str = _EMPTY_DIGEST
) -> str
```

The dataset's identity: sorted per-task digests, then `dataset.toml`, then the dataset-level files when
there are any (`dataset_files` other than the digest of nothing).

```python
nemo_gym.data.tasks.harbor.manifest.dataset_files_digest(
    folder: pathlib.Path
) -> str
```

Digest of the dataset-level Gym files that shape tasks (`DATASET_FILES`): name and content of each one
present, in order; the digest of nothing when the dataset ships none (every hub dataset).

```python
nemo_gym.data.tasks.harbor.manifest.dataset_toml_digest(
    folder: pathlib.Path
) -> str
```

Digest of `dataset.toml` alone, or of nothing when the file is absent.

```python
nemo_gym.data.tasks.harbor.manifest.enclosing_manifest(
    path: pathlib.Path,
    levels: int
) -> tuple[pathlib.Path, nemo_gym.data.tasks.harbor.manifest.Manifest] | None
```

The nearest fetched manifest above `path` whose dataset folder's check reaches `path`, with its folder.

A dataset folder's check (`check_manifest`) sees the task folders `iter_task_folders` discovers: at
most `MAX_DISCOVERY_DEPTH` levels down, never inside a hidden folder, never through a symbolic link, never
inside a task folder it found (a task's own files are its content, not more tasks). So
the folders whose manifest can hold `path` are its nearest `levels` parents, reached from `path` through
visible folders that are not links or task folders; a manifest further up, or above a hidden, linked or task
folder, belongs to a
dataset whose check never sees `path` and is not read. Only a manifest this Gym reads as a fetch's record
(a source it knows other than `local`) claims the folders below it: a `local` one is passed over (a local
folder inside a fetched dataset's range is no dataset of its own, `check_manifest` refuses to prepare it as
one, so the fetched manifest above holds its task folders), and so is a `manifest.toml` that is no record
this Gym can read, such as another tool's in a project root, or a newer Gym's, which claims nothing here and is
refused where it is the folder's own, by that folder's check. `None` when no such manifest is in reach.

```python
nemo_gym.data.tasks.harbor.manifest.gym_layer_change(
    previous: nemo_gym.data.tasks.harbor.manifest.Manifest,
    fresh: nemo_gym.data.tasks.harbor.manifest.Manifest
) -> str
```

Which part of the Gym layer differs between two manifests of one task set, for a rewrite notice.

A manifest from before the dataset digest existed (per-task digests only, see `Manifest.records_content`)
is rewritten for that alone, whatever `dataset.toml` held when it was written.

```python
nemo_gym.data.tasks.harbor.manifest.refresh_gym_layer(
    folder: pathlib.Path
) -> nemo_gym.data.tasks.harbor.manifest.Manifest | None
```

Bring a fetched manifest's Gym-layer digests up to date with `folder` without touching its task records.

A fetch records `dataset.toml` and the dataset-level Gym files as it found them, and
rewrites the manifest only when it fetches something: a registry fetch with every folder in place, or a
pull that only replaced the copy of an entry's `dataset.toml` beside the tasks
(`nemo_gym.data.tasks.harbor.entries.prepare_destination`), leaves `dataset_toml_digest` and the dataset
digest describing a file that is no longer there. This recomputes those digests from disk and keeps every
task's recorded digest and pin, and the fetch's reference, as they are (nothing is hashed, so a hand-edited
folder is still caught by `check_manifest`, which rehashes), then writes the manifest when its text
changed, with the notice `check_manifest` prints for the same rewrite (`Rewrote ...; dataset digest <old> -> <new>`), so a change of
the dataset's identity is announced whichever function applies it. Returns the manifest now on disk: `None`
without one, and the old one untouched when it records pins only (`check_manifest` upgrades those) or names a
source this Gym does not know (`check_manifest` refuses those).

```python
nemo_gym.data.tasks.harbor.manifest.report_rewrite(
    folder: pathlib.Path,
    previous: nemo_gym.data.tasks.harbor.manifest.Manifest,
    fresh: nemo_gym.data.tasks.harbor.manifest.Manifest,
    why: str
) -> None
```

The one-line notice that `folder`'s manifest was rewritten, and how the dataset digest moved.

```python
nemo_gym.data.tasks.harbor.manifest.task_differences(
    recorded: dict[str, str | None],
    on_disk: dict[str, str | None],
    unhashable: collections.abc.Iterable[str] = ()
) -> str | None
```

One line naming the tasks whose digest differs between a manifest and the folders, or `None`.

A task is `missing` when the manifest recorded its digest and the folder is gone (`on_disk` lacks
it, or maps it to `None` because its pin outlived the folder), `changed` when both digests exist
and differ, and `not in the manifest` when only the folder exists. One of `unhashable` (its folder
is there but has no digest now, see `Manifest.build`) whose digest the manifest recorded is
`cannot be hashed`, not missing.

```python
nemo_gym.data.tasks.harbor.manifest.task_folders(
    folder: pathlib.Path
) -> list[pathlib.Path]
```

The task folders under `folder`, as the loader discovers them (`iter_task_folders`: recursively,
hidden folders skipped, links not followed), sorted by path. A task is named by its folder's name there too.

```python
nemo_gym.data.tasks.harbor.manifest.tracked_by_git(
    folder: pathlib.Path
) -> bool
```

Whether git tracks files under `folder`: the repository's own example datasets, or a checkout.

Such a folder is under version control already, so prepare computes its identity in memory
instead of leaving a derived `manifest.toml` in the working tree. No git, no repository or any
other failure reads as not tracked.

```python
nemo_gym.data.tasks.harbor.manifest.DATASET_FILES = (TASK_DATA_MODULE, VERIFIER_FILE)
```

```python
nemo_gym.data.tasks.harbor.manifest.DIGEST_RECORDING_SOURCES = ('harbor-package-store',)
```

```python
nemo_gym.data.tasks.harbor.manifest.LOCAL_SOURCE = 'local'
```

```python
nemo_gym.data.tasks.harbor.manifest.MANIFEST_FILE = 'manifest.toml'
```

```python
nemo_gym.data.tasks.harbor.manifest.MANIFEST_SCHEMA_VERSION = 1
```

```python
nemo_gym.data.tasks.harbor.manifest.SOURCES = ('harbor-registry', 'harbor-package-store', 'git', 'local')
```

```python
nemo_gym.data.tasks.harbor.manifest.TASK_FILE = 'task.toml'
```

```python
nemo_gym.data.tasks.harbor.manifest.TASK_KEYS = ('digest', 'git_url', 'git_commit_id', 'path', 'package', 'content_hash')
```

```python
nemo_gym.data.tasks.harbor.manifest._EMPTY_DIGEST = hashlib.sha256(b'').hexdigest()
```

```python
nemo_gym.data.tasks.harbor.manifest._NO_HARD_LINKS = {errno.EPERM, errno.ENOTSUP, errno.EOPNOTSUPP, errno.ENOSYS, errno.EACCES}
```

```python
nemo_gym.data.tasks.harbor.manifest._SURROGATE_PAIR = re.compile('\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[c-f][0-9a-f]{2})')
```

```python
nemo_gym.data.tasks.harbor.manifest.logger = logging.getLogger(__name__)
```