diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 4fe44f9f2..f72b45744 120000 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1 +1 @@ -../openclaw/AGENTS.md \ No newline at end of file +../.openclaw/AGENTS.md \ No newline at end of file diff --git a/.claude/IDENTITY.md b/.claude/IDENTITY.md index 0ae0eecba..87638681d 120000 --- a/.claude/IDENTITY.md +++ b/.claude/IDENTITY.md @@ -1 +1 @@ -../openclaw/IDENTITY.md \ No newline at end of file +../.openclaw/IDENTITY.md \ No newline at end of file diff --git a/.claude/MEMORY.md b/.claude/MEMORY.md index ed126c1f6..cea3379b2 120000 --- a/.claude/MEMORY.md +++ b/.claude/MEMORY.md @@ -1 +1 @@ -../openclaw/MEMORY.md \ No newline at end of file +../.openclaw/MEMORY.md \ No newline at end of file diff --git a/.claude/SOUL.md b/.claude/SOUL.md index faa8e868d..ca400651c 120000 --- a/.claude/SOUL.md +++ b/.claude/SOUL.md @@ -1 +1 @@ -../openclaw/SOUL.md \ No newline at end of file +../.openclaw/SOUL.md \ No newline at end of file diff --git a/.claude/TOOLS.md b/.claude/TOOLS.md index a12dd7edb..47e96c3af 120000 --- a/.claude/TOOLS.md +++ b/.claude/TOOLS.md @@ -1 +1 @@ -../openclaw/TOOLS.md \ No newline at end of file +../.openclaw/TOOLS.md \ No newline at end of file diff --git a/.claude/USER.md b/.claude/USER.md index 12cc5c857..93357b124 120000 --- a/.claude/USER.md +++ b/.claude/USER.md @@ -1 +1 @@ -../openclaw/USER.md \ No newline at end of file +../.openclaw/USER.md \ No newline at end of file diff --git a/.claude/memory b/.claude/memory new file mode 120000 index 000000000..1c128f07d --- /dev/null +++ b/.claude/memory @@ -0,0 +1 @@ +../.openclaw/memory \ No newline at end of file diff --git a/.claude/skills b/.claude/skills index aa16b1bf4..a8b71e9a5 120000 --- a/.claude/skills +++ b/.claude/skills @@ -1 +1 @@ -../openclaw/skills \ No newline at end of file +../.openclaw/skills \ No newline at end of file diff --git a/.codex/AGENTS.md b/.codex/AGENTS.md deleted file mode 120000 index 4fe44f9f2..000000000 --- a/.codex/AGENTS.md +++ /dev/null @@ -1 +0,0 @@ -../openclaw/AGENTS.md \ No newline at end of file diff --git a/.codex/CODEX.md b/.codex/CODEX.md deleted file mode 100644 index 266ff834e..000000000 --- a/.codex/CODEX.md +++ /dev/null @@ -1,8 +0,0 @@ -Load this files automatically when startup: -- AGENTS.md -- CODEX.md -- IDENTITY.md -- MEMORY.md -- SOUL.md -- TOOLS.md -- USER.md diff --git a/.codex/CODEX.md b/.codex/CODEX.md new file mode 120000 index 000000000..f72b45744 --- /dev/null +++ b/.codex/CODEX.md @@ -0,0 +1 @@ +../.openclaw/AGENTS.md \ No newline at end of file diff --git a/.codex/IDENTITY.md b/.codex/IDENTITY.md index 0ae0eecba..87638681d 120000 --- a/.codex/IDENTITY.md +++ b/.codex/IDENTITY.md @@ -1 +1 @@ -../openclaw/IDENTITY.md \ No newline at end of file +../.openclaw/IDENTITY.md \ No newline at end of file diff --git a/.codex/MEMORY.md b/.codex/MEMORY.md index ed126c1f6..cea3379b2 120000 --- a/.codex/MEMORY.md +++ b/.codex/MEMORY.md @@ -1 +1 @@ -../openclaw/MEMORY.md \ No newline at end of file +../.openclaw/MEMORY.md \ No newline at end of file diff --git a/.codex/SOUL.md b/.codex/SOUL.md index faa8e868d..ca400651c 120000 --- a/.codex/SOUL.md +++ b/.codex/SOUL.md @@ -1 +1 @@ -../openclaw/SOUL.md \ No newline at end of file +../.openclaw/SOUL.md \ No newline at end of file diff --git a/.codex/TOOLS.md b/.codex/TOOLS.md index a12dd7edb..47e96c3af 120000 --- a/.codex/TOOLS.md +++ b/.codex/TOOLS.md @@ -1 +1 @@ -../openclaw/TOOLS.md \ No newline at end of file +../.openclaw/TOOLS.md \ No newline at end of file diff --git a/.codex/USER.md b/.codex/USER.md index 12cc5c857..93357b124 120000 --- a/.codex/USER.md +++ b/.codex/USER.md @@ -1 +1 @@ -../openclaw/USER.md \ No newline at end of file +../.openclaw/USER.md \ No newline at end of file diff --git a/.codex/memory b/.codex/memory new file mode 120000 index 000000000..1c128f07d --- /dev/null +++ b/.codex/memory @@ -0,0 +1 @@ +../.openclaw/memory \ No newline at end of file diff --git a/.codex/skills b/.codex/skills index aa16b1bf4..a8b71e9a5 120000 --- a/.codex/skills +++ b/.codex/skills @@ -1 +1 @@ -../openclaw/skills \ No newline at end of file +../.openclaw/skills \ No newline at end of file diff --git a/.kiro/memory b/.kiro/memory new file mode 120000 index 000000000..1c128f07d --- /dev/null +++ b/.kiro/memory @@ -0,0 +1 @@ +../.openclaw/memory \ No newline at end of file diff --git a/.kiro/skills b/.kiro/skills index aa16b1bf4..a8b71e9a5 120000 --- a/.kiro/skills +++ b/.kiro/skills @@ -1 +1 @@ -../openclaw/skills \ No newline at end of file +../.openclaw/skills \ No newline at end of file diff --git a/.kiro/steering/AGENTS.md b/.kiro/steering/AGENTS.md index 3e8dd8dcb..f31f9c1cd 120000 --- a/.kiro/steering/AGENTS.md +++ b/.kiro/steering/AGENTS.md @@ -1 +1 @@ -../../openclaw/AGENTS.md \ No newline at end of file +../../.openclaw/AGENTS.md \ No newline at end of file diff --git a/.kiro/steering/IDENTITY.md b/.kiro/steering/IDENTITY.md index ae5aea135..3342875a2 120000 --- a/.kiro/steering/IDENTITY.md +++ b/.kiro/steering/IDENTITY.md @@ -1 +1 @@ -../../openclaw/IDENTITY.md \ No newline at end of file +../../.openclaw/IDENTITY.md \ No newline at end of file diff --git a/.kiro/steering/MEMORY.md b/.kiro/steering/MEMORY.md index 75bdb9879..4880107fa 120000 --- a/.kiro/steering/MEMORY.md +++ b/.kiro/steering/MEMORY.md @@ -1 +1 @@ -../../openclaw/MEMORY.md \ No newline at end of file +../../.openclaw/MEMORY.md \ No newline at end of file diff --git a/.kiro/steering/SOUL.md b/.kiro/steering/SOUL.md index 2a548022f..0e7fb3793 120000 --- a/.kiro/steering/SOUL.md +++ b/.kiro/steering/SOUL.md @@ -1 +1 @@ -../../openclaw/SOUL.md \ No newline at end of file +../../.openclaw/SOUL.md \ No newline at end of file diff --git a/.kiro/steering/TOOLS.md b/.kiro/steering/TOOLS.md index 84cbd1b3a..374095dd0 120000 --- a/.kiro/steering/TOOLS.md +++ b/.kiro/steering/TOOLS.md @@ -1 +1 @@ -../../openclaw/TOOLS.md \ No newline at end of file +../../.openclaw/TOOLS.md \ No newline at end of file diff --git a/.kiro/steering/USER.md b/.kiro/steering/USER.md index dbfcdae9e..465761d1d 120000 --- a/.kiro/steering/USER.md +++ b/.kiro/steering/USER.md @@ -1 +1 @@ -../../openclaw/USER.md \ No newline at end of file +../../.openclaw/USER.md \ No newline at end of file diff --git a/.openclaw/MEMORY.md b/.openclaw/MEMORY.md index a87773ffc..e555cf754 100644 --- a/.openclaw/MEMORY.md +++ b/.openclaw/MEMORY.md @@ -9,7 +9,7 @@ - William (username: winlin), timezone America/Toronto (Eastern) - Created SRS in 2013, MIT licensed, global contributor base - SRS = Simple Realtime Server (real-time media server) -- Repo: $HOME/git/srs | Workspace: $HOME/git/srs/openclaw +- Repo: $HOME/git/srs | Workspace: $HOME/git/srs/.openclaw - Key areas to learn: protocols, architecture, state-threads (ST) coroutine library, codebase history, design decisions - William will teach me the project — I need to absorb everything diff --git a/.openclaw/TOOLS.md b/.openclaw/TOOLS.md index 549069bba..baf770240 100644 --- a/.openclaw/TOOLS.md +++ b/.openclaw/TOOLS.md @@ -42,9 +42,9 @@ Skills are shared. Your setup is yours. Keeping them apart means you can update ### ACP Working Directory -- My OpenClaw workspace may be a subdirectory like `~/git/srs/openclaw`. That is **my assistant workspace**, not necessarily the real project directory for ACP coding work. +- My OpenClaw workspace may be a subdirectory like `~/git/srs/.openclaw`. That is **my assistant workspace**, not necessarily the real project directory for ACP coding work. - When delegating project work to ACP agents (Claude/Codex/Gemini/Kiro/etc), do **not** assume the OpenClaw workspace is the project root. -- First ask: **Is the real project directory the parent of the current OpenClaw workspace?** In this setup, yes: workspace is `~/git/srs/openclaw`, while the SRS project directory is the **parent directory** `~/git/srs`. +- First ask: **Is the real project directory the parent of the current OpenClaw workspace?** In this setup, yes: workspace is `~/git/srs/.openclaw`, while the SRS project directory is the **parent directory** `~/git/srs`. - Treat this as the default pattern unless the task clearly targets OpenClaw itself: **workspace = assistant home, parent directory = actual project root**. - For ACP project tasks, prefer the **parent directory of the current workspace** as cwd when that parent is the real repo/project root. - Use the OpenClaw workspace itself only for OpenClaw-specific/meta tasks. diff --git a/.openclaw/skills/kb-review/SKILL.md b/.openclaw/skills/kb-review/SKILL.md deleted file mode 100644 index c3174f6f6..000000000 --- a/.openclaw/skills/kb-review/SKILL.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -name: kb-review -description: Review and correct SRS knowledge base documents (memory/srs-*.md) by loading relevant source code into context and identifying inaccuracies. Use when asked to review, correct, verify, or check the knowledge base, documentation accuracy, or when someone wants to find issues in srs-overview.md or srs-coroutines.md sections. ---- - -# KB Review — Knowledge Base Accuracy Checker - -Review SRS knowledge base documents against the actual codebase to find inaccuracies. - -## Setup - -Do **not** hardcode an absolute SRS path. Resolve `SRS_ROOT` dynamically: - -1. If `SRS_ROOT` env is set and contains `trunk/src`, use it. -2. Else, if current workspace (or its git root) contains `trunk/src`, use that. -3. Else, if `~/git/srs/trunk/src` exists, use `~/git/srs`. -4. Else, ask the user for the SRS repo root. - -All paths below are relative to `$SRS_ROOT`. - -**Key paths:** -- Knowledge base: `memory/srs-*.md` (in the workspace/openclaw dir) -- SRS source: `trunk/src/` (subdirs: app, core, kernel, protocol, utest, main) -- ST library: `trunk/3rdparty/st-srs/` -- Config: `trunk/conf/full.conf` - -## Workflow - -**Step 1: Identify target document and section** - -List files matching `memory/srs-*.md` and present them to the user. Ask the user which document and which section to review — let the user type the section name freely (do not list sections for them to pick from). - -**Step 2: Read the document section** - -Read the chosen section text fully. - -**Step 3: Identify and load all relevant source code** - -Analyze the section content — every function name, struct, config directive, protocol, file, or mechanism mentioned. Then: - -1. Determine which part of the codebase the section covers -2. Use the appropriate skill to load the code — e.g., `st-develop` skill for ST/coroutine code -3. Follow that skill's loading instructions fully — do not skip files or read partially -4. If no skill exists for the relevant codebase area, search and load the files directly - -The goal: have every piece of code the section describes loaded in context before reviewing. - -**Step 4: Review and report issues** - -Compare every claim in the document against the loaded source code. Check for: - -- **Factual errors** — Function names, struct names, variable names that don't match code -- **Outdated info** — Behavior described that no longer matches current implementation -- **Missing context** — Important details in the code not mentioned in the doc -- **Wrong mechanics** — Incorrect description of how something works vs what the code actually does -- **Version/date errors** — Wrong version numbers or dates (cross-check git tags if needed) -- **Config errors** — Wrong config directive names, wrong default values - -Present findings as a numbered list. For each issue: -1. Quote the problematic text from the doc -2. Explain what the code actually shows -3. Cite the specific file and line(s) - -If the section is accurate, say so — don't invent issues. - -**Step 5: Ask if user wants corrections applied** - -After presenting issues, ask if the user wants to apply fixes to the document. Only edit with explicit approval. diff --git a/.openclaw/skills/srs-learn/SKILL.md b/.openclaw/skills/srs-learn/SKILL.md deleted file mode 100644 index 1c912620e..000000000 --- a/.openclaw/skills/srs-learn/SKILL.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -name: srs-learn -description: For developers who want to become SRS contributors or maintainers — learn SRS or any of its modules (ST, protocols, media) in depth, understand detailed code and implementation, media architecture, and the underlying knowledge behind it all. The learning path for anyone who wants to touch, modify, or extend the codebase. ---- - -# SRS Learn - -## Purpose -Turn SRS knowledge base docs into hands-on learning sessions: -- Start from `memory/srs-*.md` -- Let the user choose what to learn -- Teach with real source code -- Default: create a new, standalone unit test file for the learner -- If the user explicitly requests reusing/modifying a specific existing utest file, follow the user's request instead of forcing a new file -- Build and run it successfully before moving on -- Teach workflow and debugging until the topic is understood - -## Setup -Before starting a learning session: -- Resolve `SRS_ROOT` dynamically: - 1. If `SRS_ROOT` env is set and contains `trunk/src`, use it. - 2. Else, if current workspace (or its git root) contains `trunk/src`, use that. - 3. Else, if `~/git/srs/trunk/src` exists, use `~/git/srs`. - 4. Else, ask the user for SRS repo root. -- Confirm knowledge base files exist in workspace: `memory/srs-*.md`. -- Identify the matching specialized skill for the topic (e.g. `st-develop` for ST/coroutines). A specialized skill is **required** — if none exists, abort (see Step 3). - -## Learning Workflow -Follow this sequence every time. - -1. Identify the target knowledge base. -2. Summarize concrete sections and let the user choose. -3. Find the matching specialized skill — abort if none exists. -4. Teach the section with code + new utest file (build success + run success required). -5. Explain utest workflow and debugging. -6. Confirm mastery and propose the next step. - -Do not skip user choice steps. - -## Step 1: Select Knowledge Base -List all matching files: `memory/srs-*.md`. - -Ask the user: -- Which KB file to learn now? -- What is the goal (overview, deep internals, debugging, implementation)? -- Preferred depth (quick, normal, deep)? - -If the user already specifies the KB, proceed directly. - -## Step 2: Summarize Concrete Learning Sections -Read the selected KB fully. - -Extract concrete, teachable sections and present them as a numbered menu. For each item, include: -- Section/topic name -- What the learner will master -- Main source files/functions to inspect -- A candidate utest demo idea - -Keep the menu concise and actionable (typically 3-8 items). - -Ask the user to select one item before continuing. - -## Step 3: Find Specialized Skill (Required) -After the user picks a section, identify the matching specialized skill. - -srs-learn **cannot** create, build, or run utests on its own. It relies entirely on the specialized skill for: -- Loading the correct source code context -- Creating utest files in the right location with the right patterns -- Building and running utests - -Example: for ST/coroutine topics, use `st-develop`. - -**If no matching specialized skill exists for the selected topic, abort the learning task.** Tell the user which topic/module lacks a skill and that one needs to be created before this topic can be learned through srs-learn. - -## Step 4: Teach with Code + New Unit Test -Read and follow the specialized skill identified in Step 3. It owns the build/test workflow. - -After completing build/run for a lesson, always run the specialized skill's required verifier (if defined) before declaring completion. - -By default, create a **new, standalone utest file** so each lesson has a clean, isolated artifact to study. If the user explicitly asks to continue in a specific existing utest file, modify that file instead. - -Teach in this order: - -1. Explain the concept briefly from KB (what and why). -2. Walk through the concrete code path (entry → core logic → output/effect). -3. Create a new utest file that demonstrates one specific behavior from the section. -4. Build the utest — confirm zero build errors. -5. Run the utest — confirm it passes. -6. Explain why the test passes based on code logic. - -Both **build success** and **run success** are required before the lesson is considered complete. If either fails, debug and fix, then retry. If blocked, explicitly report the blocker and current failure output. - -Unit test guidelines: -- Keep the scope narrow (one behavior per test). -- Use clear naming tied to the concept. -- Prefer deterministic inputs and assertions. -- Reuse existing utest patterns from the repository. - -## Step 5: Explain Utest Workflow -After running the test, explicitly teach the workflow: -- How test setup/fixtures map to module state -- What action triggers the behavior -- What assertions validate correctness -- How this test connects to production code flow - -Then give a debugging walkthrough: -- Where to set breakpoints/logs -- Which variables/state transitions matter most -- Common failure signatures -- How to isolate regressions quickly - -## Step 6: Mastery Check and Iteration -Ask short mastery-check questions: -- "What does this test prove?" -- "Which function is the true decision point?" -- "If this assertion fails, where do we debug first?" - -If the user wants more practice: -- Propose an extension exercise (new edge case or variation) -- Create a new utest file for it (same rules: build success + run success), unless the user explicitly asks to continue in an existing utest file -- Discuss results - -## Output Format During Sessions -Use this response structure during learning sessions: - -1. Selected section and objective -2. Code map (files/functions) -3. Unit test plan -4. Utest implementation + build/run results (must include test file path and explicit pass evidence) -5. Workflow explanation -6. Debugging checklist -7. Mastery check + next step - -Keep explanations technical and direct. Prioritize concrete code behavior over abstract theory. diff --git a/.openclaw/skills/srs-support/SKILL.md b/.openclaw/skills/srs-support/SKILL.md index 0d6e04789..c2ecea8d4 100644 --- a/.openclaw/skills/srs-support/SKILL.md +++ b/.openclaw/skills/srs-support/SKILL.md @@ -11,23 +11,22 @@ This skill is for **answering questions and providing guidance**. If the user wa ## Setup -Resolve `SRS_ROOT` dynamically (do not hardcode paths): +Do **not** hardcode an absolute SRS path. Resolve `SRS_ROOT` dynamically: -1. If `SRS_ROOT` env is set and contains `openclaw/memory/srs-overview.md`, use it. -2. Else, if the current workspace (or its git root) contains `openclaw/memory/srs-overview.md`, use that. -3. Else, if `~/git/srs/openclaw/memory/srs-overview.md` exists, use `~/git/srs`. -4. Else, ask the user for their SRS repo root. - -All paths below are relative to `$SRS_ROOT`. +1. If `SRS_ROOT` env is set and contains `trunk/src`, use it. +2. Else, if current workspace (or its git root) contains `trunk/src`, use that. +3. Else, if the parent folder of the workspace contains `trunk/src`, use that parent. +4. Else, if `~/git/srs/trunk/src` exists, use `~/git/srs`. +5. Else, ask the user for the SRS repo root. ## Loading Knowledge Load knowledge selectively based on the question topic: -- **Always load first:** `openclaw/memory/srs-overview.md` — this covers protocols, codecs, transmuxing, configuration, features, ecosystem, performance, and most support questions. -- **Load on demand:** `openclaw/memory/srs-coroutines.md` — only load this when the question is specifically about SRS architecture internals, coroutines, State Threads, or how SRS handles concurrency. Most user questions don't need this. Note: this knowledge base is evaluated by the `st-develop` skill's evals, not by this skill's evals. +- **Always load first:** `../../memory/srs-overview.md` — this covers protocols, codecs, transmuxing, configuration, features, ecosystem, performance, and most support questions. +- **Load on demand:** `../../memory/srs-coroutines.md` — only load this when the question is specifically about SRS architecture internals, coroutines, State Threads, or how SRS handles concurrency. Most user questions don't need this. Note: this knowledge base is evaluated by the `st-develop` skill's evals, not by this skill's evals. -As the knowledge base grows, new `srs-*.md` files will appear. List `openclaw/memory/srs-*.md` to discover them, and load only the ones relevant to the question. +As the knowledge base grows, new `srs-*.md` files will appear. List `../../memory/srs-*.md` to discover them, and load only the ones relevant to the question. ## Answering by Topic @@ -44,15 +43,15 @@ As the knowledge base grows, new `srs-*.md` files will appear. List `openclaw/me - Note that SRS focuses on transmuxing (repackaging without re-encoding), not transcoding ### Configuration Questions -- Reference `conf/full.conf` as the complete configuration reference +- Reference `$SRS_ROOT/conf/full.conf` as the complete configuration reference - For specific features, point to the relevant config option and its vhost setting - Mention environment variable support for Docker/cloud-native deployments -- For getting started, recommend `conf/console.conf` for local testing +- For getting started, recommend `$SRS_ROOT/console.conf` for local testing ### Deployment & Getting Started -- Provide the standard build steps: `cd srs/trunk && ./configure && make` +- Provide the standard build steps: `cd $SRS_ROOT/srs/trunk && ./configure && make` - Show the basic publish/play workflow with FFmpeg and common players -- For Docker questions, reference `conf/docker.conf` +- For Docker questions, reference `$SRS_ROOT/docker.conf` - Note that SRS is Linux-only (use WSL on Windows, macOS works for development) ### Architecture Questions @@ -82,5 +81,5 @@ As the knowledge base grows, new `srs-*.md` files will appear. List `openclaw/me - Ground every answer in the knowledge files — do not guess or invent features - When you don't have information, say so: "The knowledge base doesn't cover that yet" - Keep answers practical — include commands, config snippets, or URLs when relevant -- Use the `doc/source.flv` test file for publish examples (it ships with the repo) +- Use the `$SRS_ROOT/doc/source.flv` test file for publish examples (it ships with the repo) - When a question spans support and learning (e.g., "how does the RTMP handshake work internally?"), answer the high-level question here and suggest `srs-learn` for the deep dive diff --git a/.openclaw/skills/st-develop/SKILL.md b/.openclaw/skills/st-develop/SKILL.md index 8eb1d494e..8b3d95bab 100644 --- a/.openclaw/skills/st-develop/SKILL.md +++ b/.openclaw/skills/st-develop/SKILL.md @@ -5,23 +5,23 @@ description: Anything related to coroutines, State Threads (ST), or SRS's concur # ST Development -State Threads (ST) is a C coroutine library. Source lives in `trunk/3rdparty/st-srs/` inside the SRS repo. +State Threads (ST) is a C coroutine library. -Default SRS repo path is `~/git/srs`, but do **not** hardcode this path. -Always resolve `SRS_ROOT` dynamically: +## Setup -1. If `SRS_ROOT` env is set and contains `trunk/3rdparty/st-srs`, use it. -2. Else, if current workspace (or its git root) contains `trunk/3rdparty/st-srs`, use that. -3. Else, if `~/git/srs/trunk/3rdparty/st-srs` exists, use `~/git/srs`. -4. Else, ask the user for the SRS repo root. +Do **not** hardcode an absolute SRS path. Resolve `SRS_ROOT` dynamically: -All ST source paths below are relative to `$SRS_ROOT`. +1. If `SRS_ROOT` env is set and contains `trunk/src`, use it. +2. Else, if current workspace (or its git root) contains `trunk/src`, use that. +3. Else, if the parent folder of the workspace contains `trunk/src`, use that parent. +4. Else, if `~/git/srs/trunk/src` exists, use `~/git/srs`. +5. Else, ask the user for the SRS repo root. -## Setup: Load Knowledge Base (MANDATORY) +## Load Knowledge Base (MANDATORY) Before any ST work, use the `read` tool to load the knowledge base. Do NOT use memory_search — read the full file directly. -- `memory/srs-coroutines.md` +- `../../memory/srs-coroutines.md` ## Loading ST Source Code (ON REQUEST)