☰ GDG /
Docstrings (001–005)
#002 gdtest_google #003 gdtest_sphinx #001 gdtest_minimal #004 gdtest_nodocs #005 gdtest_mixed_docs
Layouts (006–013)
#007 gdtest_python_layout #008 gdtest_lib_layout #006 gdtest_src_layout #009 gdtest_hatch #010 gdtest_setuptools_find #011 gdtest_setup_cfg #012 gdtest_setup_py #013 gdtest_auto_discover
Exports (014–017)
#014 gdtest_no_all #016 gdtest_config_exclude #015 gdtest_all_concat #017 gdtest_auto_exclude
Object Types (018–027)
#018 gdtest_small_class #020 gdtest_dataclasses #019 gdtest_big_class #021 gdtest_enums #022 gdtest_typed_containers #023 gdtest_protocols #024 gdtest_descriptors #026 gdtest_nested_class #025 gdtest_dunders #027 gdtest_constants
Directives (028–032)
#028 gdtest_seealso #029 gdtest_nodoc #030 gdtest_user_guide_auto #031 gdtest_user_guide_sections #032 gdtest_user_guide_subdirs
User Guide (033–038)
#033 gdtest_user_guide_explicit #034 gdtest_user_guide_custom_dir #035 gdtest_user_guide_hyphen #036 gdtest_readme_rst #037 gdtest_index_qmd #038 gdtest_index_md
Landing Pages (039–043)
#039 gdtest_no_readme #040 gdtest_index_wins #041 gdtest_index_frontmatter #042 gdtest_full_extras #043 gdtest_github_contrib
Extras & Config (044–050)
#044 gdtest_cli_click #048 gdtest_name_mismatch #046 gdtest_explicit_ref #045 gdtest_cli_nested #047 gdtest_kitchen_sink #049 gdtest_src_big_class #050 gdtest_google_big_class
Cross-Dimension (051–065)
#051 gdtest_user_guide_cli #053 gdtest_src_no_all #052 gdtest_explicit_big_class #055 gdtest_google_seealso #054 gdtest_extras_guide #056 gdtest_setup_cfg_src #057 gdtest_exclude_cli #058 gdtest_src_explicit_ref #059 gdtest_async_funcs #060 gdtest_generators #061 gdtest_overloads #062 gdtest_abstract_props #063 gdtest_multi_inherit #064 gdtest_slots_class #065 gdtest_frozen_dc
API Patterns (066–077)
#066 gdtest_generics #067 gdtest_context_mgr #068 gdtest_decorators #069 gdtest_exceptions #070 gdtest_reexports #071 gdtest_many_exports #072 gdtest_deep_nesting #073 gdtest_long_docs #074 gdtest_many_guides #076 gdtest_flit #077 gdtest_pdm #075 gdtest_many_big_classes
Scale & Stress (078–082)
#078 gdtest_namespace #079 gdtest_monorepo #080 gdtest_multi_module #081 gdtest_src_legacy #082 gdtest_empty_module
Build Systems (083–088)
#083 gdtest_all_private #084 gdtest_duplicate_all #085 gdtest_badge_readme #086 gdtest_math_docs #087 gdtest_mixed_guide_ext #088 gdtest_unicode_docs
Edge Cases (089–095)
#089 gdtest_config_all_on #090 gdtest_config_display #091 gdtest_config_minimal #092 gdtest_config_parser #093 gdtest_config_extra_keys #094 gdtest_github_icon #095 gdtest_source_branch
Config Matrix (096–100)
#096 gdtest_source_path #097 gdtest_source_title #098 gdtest_source_disabled #099 gdtest_sidebar_disabled #100 gdtest_sidebar_min_items
Config Options (101–125)
#102 gdtest_cli_name #103 gdtest_dynamic_false #101 gdtest_sidebar_float #104 gdtest_parser_google #105 gdtest_parser_sphinx #106 gdtest_display_name #107 gdtest_funding #108 gdtest_authors_multi #109 gdtest_no_darkmode #110 gdtest_exclude_list #111 gdtest_jupyter_kernel #112 gdtest_config_sections #113 gdtest_config_ug_string #114 gdtest_config_ug_list #115 gdtest_config_changelog #116 gdtest_config_reference #117 gdtest_config_combo_a
#121 gdtest_config_combo_e FAIL
#118 gdtest_config_combo_b #119 gdtest_config_combo_c #120 gdtest_config_combo_d #122 gdtest_config_combo_f #123 gdtest_attribution_on #124 gdtest_attribution_off #125 gdtest_rst_versionadded
Docstring Richness (126–150)
#126 gdtest_rst_deprecated #127 gdtest_rst_note #128 gdtest_rst_warning #130 gdtest_rst_caution #129 gdtest_rst_tip #131 gdtest_rst_danger #132 gdtest_rst_important #134 gdtest_directives #133 gdtest_rst_mixed_dirs #135 gdtest_sphinx_func_role #136 gdtest_sphinx_class_role #137 gdtest_sphinx_exc_role #138 gdtest_sphinx_meth_role #139 gdtest_sphinx_mixed_roles #140 gdtest_numpy_rich #141 gdtest_google_rich #142 gdtest_sphinx_rich #143 gdtest_docstring_examples #144 gdtest_examples_rst_repro #145 gdtest_docstring_notes #146 gdtest_docstring_warnings #147 gdtest_docstring_references #148 gdtest_docstring_seealso #150 gdtest_docstring_tables #149 gdtest_docstring_math
UG Variations (151–165)
#151 gdtest_docstring_combo #152 gdtest_ug_auto #153 gdtest_ug_numbered #154 gdtest_ug_sections_fm #155 gdtest_ug_subdirs #156 gdtest_ug_custom_dir #157 gdtest_ug_deep_nest #158 gdtest_ug_mixed_ext #160 gdtest_ug_explicit_order #159 gdtest_ug_many_pages #162 gdtest_ug_no_frontmatter #161 gdtest_ug_single_page #164 gdtest_ug_with_images #163 gdtest_ug_with_code #165 gdtest_ug_hyphen_dir
Custom Sections (166–175)
#166 gdtest_ug_combo #167 gdtest_sec_examples #168 gdtest_sec_tutorials #169 gdtest_sec_recipes #170 gdtest_sec_blog #171 gdtest_sec_faq #172 gdtest_sec_multi #173 gdtest_sec_navbar_after #174 gdtest_sec_with_ug #175 gdtest_sec_with_ref
Reference Config (176–185)
#176 gdtest_sec_deep #177 gdtest_sec_index_opt #178 gdtest_sec_index_hero #179 gdtest_sec_sidebar_single #180 gdtest_custom_passthrough_navbar #181 gdtest_custom_raw_navbar_after #182 gdtest_custom_mixed_modes #183 gdtest_custom_nested_combo #184 gdtest_custom_basename_output #185 gdtest_custom_nested_output
Site Theming (186–195)
#186 gdtest_custom_missing_dir_combo #187 gdtest_ref_explicit #188 gdtest_ref_members_false #189 gdtest_ref_mixed #190 gdtest_ref_reorder #192 gdtest_ref_single_section #191 gdtest_ref_sectioned #193 gdtest_ref_module_expand #194 gdtest_ref_big_class #195 gdtest_ref_multi_big
Stress Tests (196–200)
#196 gdtest_ref_title #197 gdtest_theme_cosmo #198 gdtest_theme_lumen #199 gdtest_theme_cerulean #200 gdtest_toc_disabled #201 gdtest_toc_depth #202 gdtest_toc_title #203 gdtest_site_combo #204 gdtest_display_badges #205 gdtest_display_authors #206 gdtest_display_funding #207 gdtest_stress_all_config #208 gdtest_stress_all_docstr #209 gdtest_stress_all_ug #210 gdtest_stress_all_sections #212 gdtest_src_google_seealso #211 gdtest_stress_everything #213 gdtest_hatch_nodoc #214 gdtest_pdm_big_class #215 gdtest_flit_enums #216 gdtest_namespace_ug #217 gdtest_ug_subdir_numbered #218 gdtest_homepage_ug #220 gdtest_logo #221 gdtest_hero_basic #222 gdtest_hero_readme_badges #219 gdtest_long_names #223 gdtest_hero_disabled #224 gdtest_hero_custom #225 gdtest_hero_wordmark #226 gdtest_hero_no_logo #227 gdtest_hero_explicit_badges #228 gdtest_hero_index_qmd #229 gdtest_hero_auto_logo #230 gdtest_md_disabled #231 gdtest_md_no_widget #232 gdtest_announce_simple #233 gdtest_announce_dict #234 gdtest_announce_disabled #235 gdtest_gradient_sky #236 gdtest_gradient_peach #237 gdtest_gradient_prism #238 gdtest_gradient_lilac #239 gdtest_gradient_slate #240 gdtest_gradient_honey #241 gdtest_gradient_dusk #242 gdtest_gradient_mint #243 gdtest_gradient_navbar #244 gdtest_gradient_both #245 gdtest_gradient_mixed #246 gdtest_gradient_no_dismiss #247 gdtest_header_text #248 gdtest_header_list #249 gdtest_header_file #250 gdtest_navbar_color #251 gdtest_navbar_color_light #252 gdtest_navbar_color_dark #253 gdtest_navbar_color_same #254 gdtest_navbar_color_split #256 gdtest_stress_everything_q #255 gdtest_kitchen_sink_q #257 gdtest_seealso_desc #258 gdtest_numpy_seealso_desc #259 gdtest_interlinks_prose #260 gdtest_autolink #261 gdtest_skill_default #262 gdtest_skill_curated #264 gdtest_skill_disabled #263 gdtest_skill_config #265 gdtest_skill_rich #266 gdtest_skill_combo #267 gdtest_skill_complex #268 gdtest_i18n_french #269 gdtest_i18n_japanese #270 gdtest_i18n_arabic #271 gdtest_code_cells #273 gdtest_page_tags #272 gdtest_nav_icons #274 gdtest_page_status #277 gdtest_homepage_ug_subdirs #275 gdtest_tag_location #276 gdtest_icon_shortcode #278 gdtest_gt_tables #281 gdtest_homepage_wide #282 gdtest_interlinks_userguide #279 gdtest_scale_to_fit #280 gdtest_scale_min_scale #283 gdtest_code_span_headings #286 gdtest_namespace_src #284 gdtest_sec_blog_user_index #285 gdtest_sec_dir_titles #287 gdtest_auto_include #288 gdtest_no_auto_exclude #290 gdtest_tbl_shortcode #292 gdtest_hr_shortcode #293 gdtest_accent_color #294 gdtest_keys_shortcode #291 gdtest_tbl_explorer #289 gdtest_tbl_preview #296 gdtest_inline_always #295 gdtest_inline_methods #297 gdtest_inline_never #298 gdtest_inline_threshold #299 gdtest_ref_inherited_explicit #300 gdtest_ref_include_inherited #304 gdtest_lightbox #302 gdtest_details_shortcode #303 gdtest_termshow #301 gdtest_mock_code #305 gdtest_hero_no_name #306 gdtest_sec_nested_tags #307 gdtest_sec_xref_subdirs #308 gdtest_bibliography #311 gdtest_go_cli #309 gdtest_bibliography_csl #310 gdtest_custom_css #312 gdtest_ug_dark_assets #313 gdtest_code_include #314 gdtest_ug_mixed_subdir_order #315 gdtest_type_aliases
314/315 built ⏱ 1m 3s 🧪 19/19

AI / Agents

Skills
llms.txt
llms-full.txt

Meta

Requires: Python >=3.10
Package Info

gdtest-skill-complex

A task-orchestration framework with comprehensive agent skill documentation including reference cheatsheets, setup scripts, and configuration templates.

Installation

pip install gdtest-skill-complex

Sophisticated skill composition: curated SKILL.md accompanied by the full Agent Skills directory structure — references/ (API cheatsheet, migration guide), scripts/ (setup helper, test runner), and assets/ (config template). The SKILL.md body cross-references companion files with directory tree diagrams, tables, and embedded code samples. Tests that the raw rendering handles complex multi-file skill structures.

Source files
📁 gdtest_skill_complex/
📄 __init__.py
"""A task-orchestration framework."""

__version__ = "3.1.0"
__all__ = [
    "Scheduler",
    "Task",
    "CronExpr",
    "TaskResult",
    "every",
    "cron",
    "once",
    "chain",
]


class Scheduler:
    """
    Central task scheduler with worker pool.

    Parameters
    ----------
    workers
        Number of concurrent worker threads.
    name
        Scheduler instance identifier.
    """

    def __init__(self, workers: int = 1, name: str = "default"):
        self.workers = workers
        self.name = name
        self._tasks: list = []

    def every(self, seconds: int, fn=None, name: str = "") -> "Task":
        """
        Schedule a recurring task at a fixed interval.

        Parameters
        ----------
        seconds
            Interval in seconds between executions.
        fn
            Callable to execute.
        name
            Task identifier.

        Returns
        -------
        Task
            The registered task.
        """
        t = Task(name=name or "interval", fn=fn)
        self._tasks.append(t)
        return t

    def cron(self, expr: str, fn=None, name: str = "") -> "Task":
        """
        Schedule a task using a cron expression.

        Parameters
        ----------
        expr
            Cron expression (e.g., ``*/5 * * * *``).
        fn
            Callable to execute.
        name
            Task identifier.

        Returns
        -------
        Task
            The registered task.
        """
        CronExpr(expr)  # validate
        t = Task(name=name or "cron", fn=fn)
        self._tasks.append(t)
        return t

    def once(self, delay: int, fn=None, name: str = "") -> "Task":
        """
        Schedule a one-shot task after a delay.

        Parameters
        ----------
        delay
            Delay in seconds before execution.
        fn
            Callable to execute.
        name
            Task identifier.

        Returns
        -------
        Task
            The registered task.
        """
        t = Task(name=name or "once", fn=fn)
        self._tasks.append(t)
        return t

    def chain(self, *tasks: "Task") -> list["TaskResult"]:
        """
        Execute tasks sequentially, passing each result to the next.

        Parameters
        ----------
        *tasks
            Tasks to chain in order.

        Returns
        -------
        list[TaskResult]
            Results from each task in the chain.
        """
        return [TaskResult(task=t, status="pending") for t in tasks]

    def submit(self, fn=None, name: str = "") -> "Task":
        """
        Submit a fire-and-forget task.

        Parameters
        ----------
        fn
            Callable to execute.
        name
            Task identifier.

        Returns
        -------
        Task
            The submitted task.
        """
        t = Task(name=name or "submitted", fn=fn)
        self._tasks.append(t)
        return t

    def run(self) -> list["TaskResult"]:
        """
        Start the scheduler and block until stopped.

        Returns
        -------
        list[TaskResult]
            Results of all completed tasks.
        """
        return []

    def stop(self) -> None:
        """Stop the scheduler gracefully."""
        pass


class Task:
    """
    A unit of work managed by a Scheduler.

    Parameters
    ----------
    name
        Task identifier (must be unique within a scheduler).
    fn
        Callable to execute.
    timeout
        Maximum execution time in seconds (None = no limit).
    """

    def __init__(self, name: str, fn=None, timeout: int | None = None):
        self.name = name
        self.fn = fn
        self.timeout = timeout


class CronExpr:
    """
    A parsed cron expression.

    Parameters
    ----------
    expr
        Cron expression string (5 fields: min hour dom month dow).

    Raises
    ------
    ValueError
        If the expression is malformed.
    """

    def __init__(self, expr: str):
        parts = expr.strip().split()
        if len(parts) != 5:
            raise ValueError(
                f"Cron expression must have 5 fields, got {len(parts)}: {expr!r}"
            )
        self.expr = expr

    def matches(self, dt) -> bool:
        """
        Check if a datetime matches this cron expression.

        Parameters
        ----------
        dt
            A datetime to test.

        Returns
        -------
        bool
            True if the datetime matches.
        """
        return True


class TaskResult:
    """
    The result of a completed task.

    Parameters
    ----------
    task
        The task that produced this result.
    status
        Execution status (pending, success, failed, timeout).
    value
        Return value from the task callable.
    error
        Exception if the task failed.
    """

    def __init__(
        self,
        task: Task,
        status: str = "pending",
        value=None,
        error: Exception | None = None,
    ):
        self.task = task
        self.status = status
        self.value = value
        self.error = error


def every(seconds: int, fn=None) -> Task:
    """
    Module-level shortcut: schedule a recurring task.

    Parameters
    ----------
    seconds
        Interval between executions.
    fn
        Callable to execute.

    Returns
    -------
    Task
        The registered task.
    """
    return Scheduler().every(seconds, fn)


def cron(expr: str, fn=None) -> Task:
    """
    Module-level shortcut: schedule a cron task.

    Parameters
    ----------
    expr
        Cron expression.
    fn
        Callable to execute.

    Returns
    -------
    Task
        The registered task.
    """
    return Scheduler().cron(expr, fn)


def once(delay: int, fn=None) -> Task:
    """
    Module-level shortcut: schedule a one-shot task.

    Parameters
    ----------
    delay
        Seconds before execution.
    fn
        Callable to execute.

    Returns
    -------
    Task
        The registered task.
    """
    return Scheduler().once(delay, fn)


def chain(*tasks: Task) -> list[TaskResult]:
    """
    Module-level shortcut: chain tasks sequentially.

    Parameters
    ----------
    *tasks
        Tasks to chain.

    Returns
    -------
    list[TaskResult]
        Results from each task.
    """
    return Scheduler().chain(*tasks)
📁 skills/
📁 gdtest-skill-complex/
📁 assets/
📄 config-template.yaml
# gdtest-skill-complex starter configuration
# Copy this to your project root as scheduler-config.yaml

scheduler:
  workers: 4
  name: production

tasks:
  - name: healthcheck
    type: every
    seconds: 30
    fn: app.health.check

  - name: nightly-backup
    type: cron
    expr: "0 2 * * *"
    fn: app.backup.run
    timeout: 3600

  - name: weekly-report
    type: cron
    expr: "0 9 * * 1"
    fn: app.reports.weekly

  - name: data-cleanup
    type: cron
    expr: "0 3 * * 0"
    fn: app.maintenance.cleanup
    timeout: 7200
📁 references/
📄 api-cheatsheet.md
# API Cheatsheet — gdtest-skill-complex

## Classes

| Class | Constructor | Key Methods |
|-------|------------|-------------|
| `Scheduler` | `(workers=1, name='default')` | `.every()`, `.cron()`, `.once()`, `.submit()`, `.chain()`, `.run()`, `.stop()` |
| `Task` | `(name, fn=None, timeout=None)` | — |
| `CronExpr` | `(expr)` | `.matches(dt)` |
| `TaskResult` | `(task, status, value, error)` | — |

## Module-level functions

| Function | Signature | Equivalent to |
|----------|-----------|---------------|
| `every()` | `(seconds, fn)` | `Scheduler().every(...)` |
| `cron()` | `(expr, fn)` | `Scheduler().cron(...)` |
| `once()` | `(delay, fn)` | `Scheduler().once(...)` |
| `chain()` | `(*tasks)` | `Scheduler().chain(...)` |

## Cron expression format

```
┌───────────── minute (0–59)
│ ┌─────────── hour (0–23)
│ │ ┌───────── day of month (1–31)
│ │ │ ┌─────── month (1–12)
│ │ │ │ ┌───── day of week (0–6, Sun=0)
* * * * *
```

## Common patterns

```python
# Every 30 seconds
scheduler.every(seconds=30, fn=poll)

# Every 5 minutes (cron)
scheduler.cron("*/5 * * * *", fn=check)

# Weekdays at 9 AM
scheduler.cron("0 9 * * 1-5", fn=report)

# One-shot in 2 minutes
scheduler.once(delay=120, fn=migrate)

# Sequential pipeline
scheduler.chain(task_a, task_b, task_c)
```
📄 migration-v2-v3.md
# Migration Guide: v2 → v3

## Breaking changes

### 1. `Scheduler.interval()` → `Scheduler.every()`

```python
# v2 (removed)
scheduler.interval(30, fn=poll)

# v3
scheduler.every(seconds=30, fn=poll)
```

### 2. `Task.callback` → `Task.fn`

```python
# v2
task = Task("name", callback=my_func)

# v3
task = Task("name", fn=my_func)
```

### 3. CronExpr validates eagerly

```python
# v2: no error until .matches() called
expr = CronExpr("bad")
expr.matches(now)  # ValueError here

# v3: error on construction
expr = CronExpr("bad")  # ValueError here
```

### 4. Worker default changed

| Setting | v2 | v3 |
|---------|----|----|
| `Scheduler(workers=...)` | `os.cpu_count()` | `1` |

Set `workers` explicitly to preserve v2 behavior:

```python
import os
scheduler = Scheduler(workers=os.cpu_count())
```

## Non-breaking additions

- `scheduler.submit()` — fire-and-forget tasks
- `scheduler.chain()` — sequential task pipelines
- `TaskResult.error` — exception capture on failure
- `Task.timeout` — per-task execution time limit
📁 scripts/
📄 run-tests.sh
#!/usr/bin/env bash
# Run test suite with coverage for gdtest-skill-complex
set -euo pipefail

echo "Running tests with coverage..."
pytest tests/ \
    --cov=gdtest_skill_complex \
    --cov-report=term-missing \
    --cov-fail-under=80

echo "Tests complete."
📄 setup-env.sh
#!/usr/bin/env bash
# Setup development environment for gdtest-skill-complex
set -euo pipefail

echo "Creating virtual environment..."
python -m venv .venv
source .venv/bin/activate

echo "Installing package with dev extras..."
pip install -e ".[dev,test]"

echo "Running initial validation..."
python -c "from gdtest_skill_complex import Scheduler; print('Import OK')"

echo "Environment ready."
📄 SKILL.md
---
name: gdtest-skill-complex
description: >
  Orchestrate recurring, cron-scheduled, and one-shot tasks with
  gdtest-skill-complex. Supports worker pools, task chaining,
  cron expressions, timeouts, and fire-and-forget patterns.
license: MIT
compatibility: Requires Python >=3.10.
metadata:
  author: gdg-test-suite
  version: "3.1"
  tags:
    - task-scheduling
    - cron
    - orchestration
    - worker-pool
---

# gdtest-skill-complex

A task-orchestration framework for scheduling, chaining, and
monitoring background work.

## Quick start

```python
from gdtest_skill_complex import Scheduler

sched = Scheduler(workers=4)
sched.every(seconds=60, fn=check_health, name="healthcheck")
sched.cron("0 2 * * *", fn=nightly_backup, name="backup")
sched.run()
```

## Skill directory structure

This skill ships with companion files for agent consumption:

```
skills/gdtest-skill-complex/
├── SKILL.md              ← This file
├── references/
│   ├── api-cheatsheet.md ← Quick-reference for all public APIs
│   └── migration-v2-v3.md ← Migration guide from v2 to v3
├── scripts/
│   ├── setup-env.sh      ← Environment bootstrap script
│   └── run-tests.sh      ← Test runner with coverage
└── assets/
    └── config-template.yaml ← Starter configuration file
```

## When to use what

| Need | Use |
|------|-----|
| Fixed-interval polling | `scheduler.every(seconds=30, fn=poll)` |
| Cron-scheduled jobs | `scheduler.cron('*/5 * * * *', fn=job)` |
| One-shot delayed task | `scheduler.once(delay=120, fn=migrate)` |
| Sequential pipeline | `scheduler.chain(extract, transform, load)` |
| Fire-and-forget | `scheduler.submit(fn=send_email)` |
| Concurrent workers | `Scheduler(workers=cpu_count())` |

## Core concepts

### Scheduler

The `Scheduler` manages a pool of workers and a task registry.
Tasks are added via `.every()`, `.cron()`, `.once()`, or `.submit()`.
Call `.run()` to start blocking execution, or `.stop()` to shut down
gracefully.

### Task

A `Task` wraps a callable with a unique name and optional timeout.
Task names **must be unique** within a scheduler — duplicates raise
`DuplicateTaskError`.

### CronExpr

Parses and evaluates standard 5-field cron expressions
(minute, hour, day-of-month, month, day-of-week). Does **not**
support second-level granularity.

```python
from gdtest_skill_complex import CronExpr

expr = CronExpr("*/5 * * * *")   # every 5 minutes
expr.matches(datetime.now())       # True/False
```

### TaskResult

Returned by `.run()` and `.chain()`. Contains the execution status
(`pending`, `success`, `failed`, `timeout`), the return value, and
any exception.

## Task chaining

Chain tasks to build sequential pipelines where each task's output
feeds the next:

```python
extract = Task("extract", fn=extract_data)
transform = Task("transform", fn=clean_and_normalize)
load = Task("load", fn=write_to_db)

results = scheduler.chain(extract, transform, load)
for r in results:
    print(f"{r.task.name}: {r.status}")
```

## Reference files

### API cheatsheet (`references/api-cheatsheet.md`)

A condensed reference of every public class and function:

| Symbol | Signature | Purpose |
|--------|-----------|---------|
| `Scheduler` | `(workers=1, name='default')` | Central orchestrator |
| `Task` | `(name, fn=None, timeout=None)` | Unit of work |
| `CronExpr` | `(expr)` | Cron parser |
| `TaskResult` | `(task, status, value, error)` | Execution result |
| `every()` | `(seconds, fn)` | Module-level interval shortcut |
| `cron()` | `(expr, fn)` | Module-level cron shortcut |
| `once()` | `(delay, fn)` | Module-level one-shot shortcut |
| `chain()` | `(*tasks)` | Module-level chain shortcut |

### Migration guide (`references/migration-v2-v3.md`)

Key changes from v2 to v3:

1. `Scheduler.interval()` renamed to `Scheduler.every()`.
2. `Task.callback` renamed to `Task.fn`.
3. `CronExpr` now validates on construction (was lazy).
4. Worker count defaults to 1 (was `os.cpu_count()`).

## Scripts

### `scripts/setup-env.sh`

Bootstrap a development environment:

```bash
#!/usr/bin/env bash
set -euo pipefail
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,test]"
echo "Environment ready."
```

### `scripts/run-tests.sh`

Run the test suite with coverage:

```bash
#!/usr/bin/env bash
set -euo pipefail
pytest tests/ --cov=gdtest_skill_complex --cov-report=term-missing
```

## Configuration template

The `assets/config-template.yaml` provides a starter configuration:

```yaml
# gdtest-skill-complex configuration
scheduler:
  workers: 4
  name: production

tasks:
  - name: healthcheck
    type: every
    seconds: 30
    fn: app.health.check

  - name: nightly-backup
    type: cron
    expr: "0 2 * * *"
    fn: app.backup.run
    timeout: 3600

  - name: weekly-report
    type: cron
    expr: "0 9 * * 1"
    fn: app.reports.weekly
```

## Error handling

```python
results = scheduler.run()
for r in results:
    if r.status == "failed":
        print(f"Task {r.task.name} failed: {r.error}")
    elif r.status == "timeout":
        print(f"Task {r.task.name} timed out after {r.task.timeout}s")
```

## Capabilities and boundaries

**What agents can configure:**

- Create schedulers with worker pools
- Register interval, cron, one-shot, and fire-and-forget tasks
- Chain tasks into sequential pipelines
- Set per-task timeouts
- Parse and validate cron expressions
- Use reference files for quick API lookups
- Run setup and test scripts

**Requires human setup:**

- Deploying as a system service (systemd, Docker, etc.)
- Configuring monitoring and alerting
- Setting up log aggregation
- Database and credential provisioning

## Resources

- [llms.txt](llms.txt) — Indexed API reference for LLMs
- [llms-full.txt](llms-full.txt) — Comprehensive documentation for LLMs
📄 README.md
# gdtest-skill-complex

A task-orchestration framework with comprehensive agent skill
documentation including reference cheatsheets, setup scripts,
and configuration templates.

## Installation

```bash
pip install gdtest-skill-complex
```
📄 great-docs.yml
site_url: "https://example.com/gdtest-skill-complex"
skill:
  gotchas:
    - "`Scheduler.tick()` is not re-entrant — never call it from inside a task callback."
    - "Task names must be unique within a `Scheduler` instance; duplicates raise `DuplicateTaskError`."
    - "The `CronExpr` parser does not support second-level granularity — minimum resolution is one minute."
  best_practices:
    - "Use `Scheduler(workers=N)` to match your CPU core count for CPU-bound tasks."
    - "Always set `task.timeout` to avoid runaway tasks — the default is no timeout."
    - "Prefer `Scheduler.submit()` over `Scheduler.run()` for fire-and-forget patterns."
  decision_table:
    - if: Running tasks on a fixed interval
      then: "scheduler.every(seconds=30, fn=task)"
    - if: Running tasks on a cron schedule
      then: "scheduler.cron('*/5 * * * *', fn=task)"
    - if: Running a one-shot delayed task
      then: "scheduler.once(delay=60, fn=task)"
    - if: Running tasks concurrently
      then: scheduler = Scheduler(workers=4)
    - if: Need task dependency chains
      then: "scheduler.chain(task_a, task_b, task_c)"