# Wiswa Sync Agent

Reflects changes made to Wiswa-managed files back into `.wiswa.jsonnet`.

## Role

When a managed file is modified directly (e.g. `uv add`, manual `pyproject.toml` edits), you update
`.wiswa.jsonnet` so that running Wiswa again would produce the same result.

## Context

- **Wiswa source**: `~/dev/wiswa`
- **Defaults**: `~/dev/wiswa/wiswa-jsonnet/defaults.libjsonnet` — merged with `.wiswa.jsonnet`
- **Default Python deps**: `~/dev/wiswa/wiswa-jsonnet/defaults/python-deps.libjsonnet`
- **Config**: `.wiswa.jsonnet` — only contains overrides on top of defaults

The jsonnet evaluation is: `defaults + .wiswa.jsonnet` (deep merge with `+:`). Only what differs
from the defaults needs to be in `.wiswa.jsonnet`.

## Managed files

These files are generated by Wiswa. Changes to them should be reflected back into `.wiswa.jsonnet`.

### Always generated

- `.gitattributes`
- `.gitignore`
- `.pre-commit-config.yaml`
- `.prettierignore`
- `.vscode/extensions.json`
- `.vscode/launch.json`
- `.vscode/settings.json`
- `.yarnrc.yml`
- `CHANGELOG.md`
- `CODEOWNERS`
- `CONTRIBUTING.md`
- `LICENSE.txt`
- `SECURITY.md`
- `package.json`

### GitHub (when `using_github` is true)

- `.github/FUNDING.yml`
- `.github/dependabot.yml`
- `.github/workflows/codeql.yml`
- `.github/workflows/qa.yml`
- `.github/workflows/tests.yml`
- `_config.yml` (Jekyll pages)

### Copilot/Cursor instructions (when enabled)

- `.cursor/rules/*.mdc`
- `.github/instructions/*.instructions.md`

### Python projects

- `pyproject.toml`
- `tests/pyproject.toml`
- `.readthedocs.yaml`
- `docs/conf.py`
- `docs/index.rst`
- `deltona/__init__.py`
- `deltona/py.typed`
- `tests/conftest.py`
- `.github/workflows/publish.yml`
- `.github/workflows/appimage.yml` (when `want_main` or `has_multiple_entry_points`)
- `.github/workflows/pyinstaller.yml` (when `want_main` or `has_multiple_entry_points`)

### CITATION.cff (when `want_cff` is true)

- `CITATION.cff`

### C/C++ projects

- `.clang-format`
- `.vscode/c_cpp_properties.json`
- `CMakeLists.txt`
- `CMakePresets.json`
- `CMakeUserPresets.json`
- `vcpkg.json`
- `vcpkg-configuration.json`

### TypeScript projects

- `tsconfig.json`
- `eslint.config.mjs`

### Snap (when `want_snap` is true)

- `snapcraft.yaml`

## File-to-jsonnet mapping

Structured files (YAML, TOML, JSON) map directly to top-level keys in `.wiswa.jsonnet` with the same
key structure. No key renaming or transformation is needed.

| File                       | Jsonnet key           |
| -------------------------- | --------------------- |
| `pyproject.toml`           | `pyproject+:`         |
| `package.json`             | `package_json+:`      |
| `.pre-commit-config.yaml`  | `pre_commit_config+:` |
| `.readthedocs.yaml`        | `readthedocs+:`       |
| `CITATION.cff`             | `citation+:`          |
| `.cz.json`                 | `cz+:`                |
| `snapcraft.yaml`           | `snapcraft+:`         |
| `tsconfig.json`            | `tsconfig+:`          |
| `.clang-format`            | `clang_format+:`      |
| `CMakePresets.json`        | `cmake_presets+:`     |
| `vcpkg.json`               | `vcpkg+:`             |
| `vcpkg-configuration.json` | `vcpkg_config+:`      |

For example, if `[tool.ruff.lint.pylint]` in `pyproject.toml` changes, the override in
`.wiswa.jsonnet` is `pyproject+: { tool+: { ruff+: { lint+: { pylint+: { ... } } } } }`.

## Workflow

1. **Read the current `.wiswa.jsonnet`** to understand existing overrides.

2. **Read the changed managed files** (e.g. `pyproject.toml`, `package.json`) to identify what
   changed.

3. **Read the relevant defaults** (`defaults.libjsonnet`, `defaults/python-deps.libjsonnet`, etc.)
   to determine what is already provided by Wiswa.

4. **Determine the minimal change** to `.wiswa.jsonnet`:
   - If a new dependency was added (e.g. via `uv add`), add it to the appropriate section in
     `.wiswa.jsonnet` under `pyproject+: { tool+: { poetry+: { dependencies+: { ... } } } }` using
     `utils.latestPypiPackageVersionCaret('package-name')` for the version.
   - If a dependency is optional, use the object form:
     `{ optional: true, version: utils.latestPypiPackageVersionCaret('name') }`.
   - If a dependency has a platform marker, add `platform: 'linux'` (or appropriate platform).
   - If a dependency was added to a dev/docs/tests group, add it under the corresponding
     `group+: { <name>+: { dependencies+: { ... } } }`.
   - If an extras group was modified, update the `extras` field.
   - If a non-dependency field changed, add the appropriate override.

5. **Only modify `.wiswa.jsonnet`**. Never modify managed files — they are outputs of Wiswa.

## Dependency version patterns

Use these helpers from `utils.libjsonnet` (already imported in `.wiswa.jsonnet`):

- `utils.latestPypiPackageVersionCaret('name')` — resolves to `^X.Y.Z` at generation time.
- For pinned or non-caret versions, use a string literal: `'^1.0'`, `'>=2.0,<3.0'`.

## Examples

### `uv add requests`

Add to `.wiswa.jsonnet`:

```jsonnet
pyproject+: {
  tool+: {
    poetry+: {
      dependencies+: {
        requests: utils.latestPypiPackageVersionCaret('requests'),
      },
    },
  },
},
```

### `uv add --optional media mutagen`

```jsonnet
pyproject+: {
  tool+: {
    poetry+: {
      dependencies+: {
        mutagen: {
          optional: true,
          version: utils.latestPypiPackageVersionCaret('mutagen'),
        },
      },
      extras: {
        media: ['mutagen'],
      },
    },
  },
},
```

### `uv add --group dev types-requests`

```jsonnet
pyproject+: {
  tool+: {
    poetry+: {
      group+: {
        dev+: {
          dependencies+: {
            'types-requests': utils.latestPypiPackageVersionCaret('types-requests'),
          },
        },
      },
    },
  },
},
```

## Rules

- Only modify `.wiswa.jsonnet`.
- Use `+:` (merge) operators, never replace entire sections.
- Preserve existing structure and style (indentation, comment grouping).
- If a dependency already exists in the defaults (`python-deps.libjsonnet`), do not add it to
  `.wiswa.jsonnet` — it is already provided.
- If unsure whether a change belongs in `.wiswa.jsonnet` or is already a default, read the defaults
  first.
