# PPAS v0.9.5

## PipiPong Pet Animation Specification

**Document status:** v0.9.5 Implementation Baseline  
**Applicable product:** PipiPong Desktop Pet v0.9.5  
**Specification identifier:** `PPAS-0.9.5`  
**Pet package extension:** `.pppet`  
**Recommended MIME type:** `application/vnd.pipipong.pet+zip`  
**Intended audience:** PipiPong client developers, pet-package creators, Pet Package Builder developers, marketplace reviewers, and security teams  
**Document language:** English  
**Language parity:** The Simplified Chinese and English editions are intended to be semantically equivalent. If an ambiguity cannot be reconciled, the machine-readable schemas, registries, and conformance tests take precedence.  

---

## 0. Normative Language

The key words in this specification are to be interpreted as follows:

- **MUST**: an implementation or pet package is required to satisfy the stated requirement; otherwise, it does not conform to PPAS v0.9.5.
- **MUST NOT**: the stated behavior is expressly prohibited.
- **SHOULD**: the requirement is strongly recommended; an implementation that does not follow it should have a clear reason.
- **SHOULD NOT**: the behavior is generally discouraged; an implementation that uses it should have a clear reason.
- **MAY**: the capability is optional.

For any unrecognized permission, event provider, required extension, or action node, the host application MUST **fail closed**: it must reject the affected capability rather than guess how to execute it.

---

# 1. Specification Goals

PPAS v0.9.5 defines an installable, verifiable, executable, and shareable desktop-pet appearance and behavior package. A conforming pet package may contain character artwork and animation, and may also declare:

1. a set of core actions that every pet must provide;
2. additional simple or complex actions designed by the creator;
3. the circumstances under which actions are triggered;
4. which PipiPong events or computer-system events the pet wishes to observe;
5. the permissions, scope, purpose, and data-handling practices required for system-event observation; and
6. runtime priority, interruption policy, timeout, and fallback behavior for each action.

The principal goals of PPAS v0.9.5 are:

- **Compatibility**: every valid pet package can be recognized and executed by the same runtime;
- **Creative freedom**: creators can add actions, action compositions, and trigger conditions;
- **Informed consent**: users can clearly see what a package requests to observe before downloading and enabling it;
- **Least privilege**: a package may use only capabilities declared in advance and authorized by the user;
- **Safe execution**: a package cannot contain arbitrary code or access the operating system directly;
- **Cross-platform operation**: one package can target macOS and Windows through a unified protocol; and
- **Forward extensibility**: future renderer adapters such as Rive, Spine, and Live2D can be added without breaking existing packages.

---

# 2. Scope and Non-Goals of v0.9.5

## 2.1 Capabilities Required in v0.9.5

PipiPong v0.9.5 MUST support:

- importing, validating, installing, enabling, disabling, uninstalling, and rolling back `.pppet` packages;
- `sprite-sequence-v1` frame-sequence rendering;
- the eight mandatory actions in PPAS Core Minimum;
- generation of the ten actions in PPAS Core Standard through PipiPong's official **Hatch New Pet** workflow;
- custom single-clip actions;
- declarative complex action graphs;
- triggers based on internal PipiPong events;
- triggers based on user-interaction events;
- a controlled set of computer-system event triggers;
- declarations for required and optional permissions;
- per-package virtual permission isolation;
- host-side event matching and filtering;
- action priority, queuing, interruption, timeout, and fallback;
- sandboxed preview and runtime fault recovery; and
- permission-difference checks and renewed consent when a package is updated.

## 2.2 Capabilities Excluded from v0.9.5

The following are outside the scope of PPAS v0.9.5:

- arbitrary JavaScript, TypeScript, Python, Lua, Shell, WebAssembly, or native code;
- `.dll`, `.dylib`, `.node`, browser extensions, or Electron plugins;
- direct package access to the file system, network, clipboard, camera, microphone, or screen;
- direct execution of applications, control of other applications, or invocation of Codex by a package;
- custom system-event listener code;
- custom renderer plugins;
- reading file contents, window contents, keyboard input, browser history, cookies, or passwords;
- remotely loading animation, image, audio, or configuration assets; and
- uploading any system-observation data from the package itself.

If any of these capabilities are introduced in the future, they MUST use a plugin specification separate from ordinary pet packages and a more restrictive review model.

---

# 3. Conceptual Model

PPAS separates a pet package into six isolated layers:

```text
Computer system / PipiPong / user interaction
                         │
                         ▼
                System Event Providers
                         │
                         ▼
             Permission Broker + Host Filter
                         │
                         ▼
                    Trigger Engine
                         │
                         ▼
                   Pet Action Runtime
                         │
                 ┌───────┴────────┐
                 ▼                ▼
          Animation Renderer   Safe Host Capabilities
          frame sequences,     movement, scaling,
          etc.                 sound, and effects
```

The principal objects are defined as follows:

| Object | Definition |
|---|---|
| Pet Package | One installable `.pppet` package |
| Clip | One playable low-level animation asset |
| Core Action | A semantic action predefined by PipiPong, such as `core.working` |
| Custom Action | An action defined by the creator, such as `custom.throw-paper` |
| Action Graph | A declarative graph that combines animation, movement, waiting, sound, effects, and branches into a complex action |
| Event Provider | An event source implemented by PipiPong, such as foreground-application, battery, or directory-change observation |
| Trigger | A rule of the form “what happened + which conditions matched + which action to execute” |
| Capability | One controlled system-observation ability requested by a package |
| Permission Grant | User authorization for one package, version, capability, and resource scope |
| Host Filter | Host-side inspection of raw information so that only a matched result reaches the action runtime |

---

# 4. `.pppet` Container Format

## 4.1 Base Format

A `.pppet` file MUST be a standard ZIP container, with the file extension `.pppet`.

The container MUST satisfy all of the following requirements:

- all text files use UTF-8;
- all paths use `/` as the separator;
- all paths are relative;
- symbolic links, hard links, and device files are prohibited;
- `../`, absolute paths, drive letters, and other path-traversal constructs are prohibited;
- file names are case-sensitive;
- `manifest.json` exists at the package root;
- executable files and scripts are prohibited; and
- all runtime assets are included in the package and do not reference remote URLs.

## 4.2 Standard Directory Layout

```text
example-pet.pppet
├── manifest.json
├── previews/
│   ├── thumbnail.webp
│   └── cover.webp
├── animations/
│   ├── index.json
│   ├── core/
│   │   ├── idle/
│   │   ├── listening/
│   │   ├── thinking/
│   │   ├── working/
│   │   ├── success/
│   │   ├── error/
│   │   ├── clicked/
│   │   ├── dragging/
│   │   ├── wake/
│   │   └── sleep/
│   └── custom/
├── actions/
│   ├── core.json
│   ├── custom.json
│   └── graphs/
├── triggers/
│   └── triggers.json
├── capabilities/
│   └── capabilities.json
├── audio/
├── effects/
├── i18n/
│   ├── zh-CN.json
│   └── en-US.json
├── licenses/
│   └── NOTICE.txt
└── integrity.json
```

## 4.3 Required Files

| File | Required | Description |
|---|---:|---|
| `manifest.json` | Yes | Package entry point and compatibility declaration |
| `previews/thumbnail.webp` | Yes | Thumbnail for installation and marketplace views |
| `animations/index.json` | Yes | Animation-clip registry |
| `actions/core.json` | Yes | Core-action bindings |
| `actions/custom.json` | Yes | May contain an empty array, but the file must exist |
| `triggers/triggers.json` | Yes | May contain an empty array, but the file must exist |
| `capabilities/capabilities.json` | Yes | May contain an empty array, but the file must exist |
| At least one locale file | Yes | Must include the declared default locale |
| `integrity.json` | Recommended for local packages; required for marketplace packages | File hashes and signature information |

## 4.4 Resource Limits in v0.9.5

The host MUST enforce limits before and during extraction:

| Item | Maximum |
|---|---:|
| Compressed package size | 200 MiB |
| Total extracted size | 500 MiB |
| Total number of files | 5,000 |
| Single file size | 100 MiB |
| Single image dimensions | 4096 × 4096 px |
| Recommended animation canvas | 512 × 512 or 1024 × 1024 px |
| Single audio-asset duration | 30 seconds |
| Total audio size | 50 MiB |
| Number of custom actions | 256 |
| Number of triggers | 128 |
| Nodes in one action graph | 256 |
| Maximum action-graph nesting depth | 16 |
| Default maximum duration of one action | 60 seconds |

A package that exceeds any limit MUST be rejected. The host MUST NOT merely warn and continue execution.

---

# 5. `manifest.json`

## 5.1 Required Fields

```json
{
  "ppasVersion": "0.9.5",
  "packageId": "creator.alice.sleepy-pig",
  "packageVersion": "1.0.0",
  "defaultLocale": "en-US",
  "nameKey": "package.name",
  "descriptionKey": "package.description",
  "author": {
    "name": "Alice",
    "creatorId": "alice"
  },
  "license": "LicenseRef-PipiPong-Creator-Standard",
  "compatibility": {
    "minAppVersion": "0.9.5",
    "platforms": ["macos", "windows"],
    "requiredRendererProfiles": ["sprite-sequence-v1"]
  },
  "coreProfile": "PPAS-Core-Standard-0.9.5",
  "entryPoints": {
    "animations": "animations/index.json",
    "coreActions": "actions/core.json",
    "customActions": "actions/custom.json",
    "triggers": "triggers/triggers.json",
    "capabilities": "capabilities/capabilities.json"
  },
  "previews": {
    "thumbnail": "previews/thumbnail.webp",
    "cover": "previews/cover.webp"
  },
  "extensionsUsed": [],
  "extensionsRequired": [],
  "dataPractices": {
    "localProcessingOnly": true,
    "networkTransmission": "none",
    "rawEventStorage": "none",
    "hostManagedTriggerState": true
  }
}
```

## 5.2 Field Rules

### `ppasVersion`

- In v0.9.5, this field MUST be the string `"0.9.5"`.
- A package version MUST NOT be used in place of the specification version.

### `packageId`

- MUST remain stable throughout the package lifecycle;
- SHOULD use the format `creator.<creatorId>.<petSlug>`;
- may contain only lower-case ASCII letters, digits, `.`, `-`, and `_`;
- must be 3–128 characters long;
- MUST be globally unique for marketplace publication; and
- when a local import conflicts with an installed package ID, the client MUST ask the user whether to replace the package, install under a new ID, or cancel; it MUST NOT overwrite silently.

### `packageVersion`

- MUST use Semantic Versioning in `major.minor.patch` form;
- expansion of permissions or trigger scope MUST increase at least the minor version; and
- incompatible changes to action or resource structures MUST increase the major version.

### `license`

- MUST use an SPDX identifier or `LicenseRef-*`; and
- when third-party assets are included, their sources and licenses MUST be listed in `licenses/NOTICE.txt`.

### `extensionsUsed` and `extensionsRequired`

- The host MAY ignore an unrecognized optional extension listed in `extensionsUsed`.
- If the host does not recognise any extension listed in `extensionsRequired`, it MUST refuse to enable the package.
- A v0.9.5 extension MUST NOT bypass permissions, sandbox boundaries, or prohibited capabilities.

---

# 6. Animation Asset Specification

## 6.1 Required Renderer Profile in v0.9.5

PipiPong v0.9.5 MUST implement:

```text
sprite-sequence-v1
```

Rive, dotLottie, Spine, and Live2D MAY be added as adapters in later versions, but they MUST NOT be required for baseline v0.9.5 compatibility.

## 6.2 Image Formats

- WebP and PNG MUST be supported.
- WebP with transparency SHOULD be preferred.
- Assets MUST use sRGB.
- All frames in one clip SHOULD use the same canvas dimensions.
- Remote images are prohibited.
- SVG assets MUST NOT contain scripts, external resources, or other active content.

## 6.3 `animations/index.json`

```json
{
  "rendererProfile": "sprite-sequence-v1",
  "clips": [
    {
      "id": "clip.idle",
      "canvas": { "width": 1024, "height": 1024 },
      "anchor": { "x": 0.5, "y": 0.94 },
      "loop": { "mode": "infinite" },
      "frames": [
        { "src": "animations/core/idle/0001.webp", "durationMs": 83 },
        { "src": "animations/core/idle/0002.webp", "durationMs": 83 }
      ],
      "markers": [
        { "id": "action.safeToInterrupt", "frame": 1 }
      ]
    }
  ]
}
```

## 6.4 Required Clip Fields

| Field | Rule |
|---|---|
| `id` | Unique within the package; `clip.*` is recommended |
| `canvas` | Positive integer width and height |
| `anchor` | Normalised coordinates in the range 0–1 |
| `frames` | At least one frame |
| `frames[].src` | A relative path within the package |
| `frames[].durationMs` | 16–2000 ms |
| `loop.mode` | `none`, `count`, or `infinite` |
| `markers` | Optional; marker IDs must be unique within the clip |

## 6.5 Coordinate System

- The origin is at the upper-left corner of the animation canvas.
- X increases to the right; Y increases downward.
- `anchor` uses normalized 0–1 coordinates.
- `anchor` identifies the pet's principal contact point with the desktop surface.
- The default anchor is `{ "x": 0.5, "y": 0.95 }`.
- When moving the pet window, the host MUST use the anchor as the logical position rather than the image's upper-left corner.

## 6.6 Standard Markers

PPAS v0.9.5 reserves the following marker IDs:

```text
action.safeToInterrupt
action.phaseComplete
footstep.left
footstep.right
takeoff
land
grip
release
impact
effect.start
effect.end
```

Creator-defined marker IDs MUST use:

```text
custom.<slug>
```

`action.complete` does not need to be declared explicitly; reaching the end of a clip is treated as completion.

## 6.7 Audio

- v0.9.5 MUST support OGG and WAV.
- Audio assets MUST be included in the package.
- Volume values use the range 0–1.
- Default volume MUST NOT exceed 0.8.
- A package MUST NOT autoplay persistent background music.
- Users MUST be able to disable all pet-package sound effects globally in PipiPong settings.

---
# 7. Core Action Profile

## 7.1 Semantic Action Principle

PipiPong invokes standard action IDs and does not depend on a pet's internal animation file names. A pet package MUST map its own clips or action graphs to standard actions.

Example:

```json
{
  "bindings": {
    "core.idle": "clip.lazy-sit",
    "core.working": "clip.hammer-keyboard",
    "core.success": "clip.throw-confetti"
  }
}
```

## 7.2 PPAS Core Minimum: Eight Mandatory Actions

Every v0.9.5 pet package that can be enabled MUST provide the following eight actions:

| Action ID | Semantics | Form | Default behavior |
|---|---|---|---|
| `core.idle` | Default idle state | Loop | Plays when no higher-priority action is active |
| `core.listening` | Listening to the user's voice | Loop | Plays while voice listening is active |
| `core.thinking` | AI understanding, planning, or waiting | Loop | Plays during the thinking phase |
| `core.working` | Executing a task | Loop | Plays during execution |
| `core.success` | Task success or operation completed | One-shot | Returns to idle when complete |
| `core.error` | Task failure or error | One-shot | Returns to idle when complete |
| `core.clicked` | The user clicked the pet | One-shot | May be interrupted by a higher-priority event |
| `core.dragging` | The user is dragging the pet | Loop | Returns to idle or `dropped` when dragging ends |

If any Core Minimum action is missing, the package MUST be classified as incompatible and MUST NOT be enabled.

## 7.3 PPAS Core Standard: Ten Actions for the Official Hatch Workflow

PipiPong v0.9.5's **Hatch New Pet** feature MUST generate the eight Core Minimum actions plus:

| Action ID | Semantics | Form |
|---|---|---|
| `core.wake` | The pet wakes or the application starts | One-shot |
| `core.sleep` | The pet sleeps after prolonged inactivity | Loop |

The official hatch workflow therefore outputs ten core actions by default.

A third-party package that omits `core.wake` or `core.sleep` may still pass Minimum validation, but the host MUST apply these fallbacks:

```text
core.wake  → core.idle
core.sleep → core.idle
```

## 7.4 Recommended Actions

The following actions are not mandatory in v0.9.5 but are recommended:

```text
core.hover
core.dropped
core.cancelled
core.confused
core.offline
core.walk
core.run
core.jump
```

## 7.5 `actions/core.json`

```json
{
  "profile": "PPAS-Core-Standard-0.9.5",
  "bindings": {
    "core.idle": { "type": "clip", "ref": "clip.idle" },
    "core.listening": { "type": "clip", "ref": "clip.listening" },
    "core.thinking": { "type": "clip", "ref": "clip.thinking" },
    "core.working": { "type": "clip", "ref": "clip.working" },
    "core.success": { "type": "clip", "ref": "clip.success" },
    "core.error": { "type": "clip", "ref": "clip.error" },
    "core.clicked": { "type": "clip", "ref": "clip.clicked" },
    "core.dragging": { "type": "clip", "ref": "clip.dragging" },
    "core.wake": { "type": "clip", "ref": "clip.wake" },
    "core.sleep": { "type": "clip", "ref": "clip.sleep" }
  },
  "fallbacks": {
    "core.wake": "core.idle",
    "core.sleep": "core.idle",
    "core.hover": "core.idle",
    "core.dropped": "core.idle"
  }
}
```

One clip MAY temporarily be mapped to multiple core actions, although marketplace quality certification may require visually distinct core feedback.

---

# 8. Custom Actions

## 8.1 ID Rules

- A custom action ID MUST begin with `custom.`.
- Examples: `custom.drink-coffee`, `custom.throw-paper`.
- IDs MUST be unique within a package.
- The host's normalized internal ID is:

```text
<packageId>#<actionId>
```

Example:

```text
creator.alice.sleepy-pig#custom.throw-paper
```

## 8.2 Action Types

v0.9.5 supports:

1. **clip action**: directly plays one clip; and
2. **graph action**: executes one declarative action graph.

## 8.3 `actions/custom.json`

```json
{
  "actions": [
    {
      "id": "custom.throw-paper",
      "nameKey": "action.throwPaper.name",
      "descriptionKey": "action.throwPaper.description",
      "type": "graph",
      "ref": "actions/graphs/throw-paper.json",
      "tags": ["error", "comedy", "document"],
      "priority": 45,
      "interrupt": {
        "policy": "atMarker",
        "markers": ["action.safeToInterrupt"]
      },
      "maxDurationMs": 12000,
      "fallback": "core.error"
    }
  ]
}
```

## 8.4 Custom Action Fields

| Field | Rule |
|---|---|
| `id` | MUST use `custom.*` |
| `type` | `clip` or `graph` |
| `ref` | Corresponding clip ID or action-graph path |
| `tags` | Optional; used for search, random selection, and marketplace presentation |
| `priority` | 10–60; values outside the range must be clamped to the permitted range or rejected by the host |
| `interrupt.policy` | `immediate`, `atMarker`, or `afterIteration` |
| `maxDurationMs` | 100–60000 ms |
| `fallback` | MUST reference an existing action, normally a core action |

A custom action MUST NOT declare itself genuinely non-interruptible. The host always retains authority to terminate it for a safety prompt, application exit, crash recovery, direct user interaction, or equivalent host-critical condition.

---

# 9. Action Graph v0.9.5

## 9.1 Design Principle

Complex actions MUST use a declarative Action Graph. Scripts, expression evaluators, and arbitrary code are prohibited.

## 9.2 Supported Nodes

| Node | Function |
|---|---|
| `sequence` | Executes child nodes in order |
| `parallel` | Executes child nodes concurrently |
| `playClip` | Plays an animation clip |
| `wait` | Waits for a fixed duration |
| `waitMarker` | Waits for the currently playing clip to reach a marker |
| `movePet` | Moves the pet window |
| `transformPet` | Scales, rotates, or horizontally flips the pet |
| `playSound` | Plays an audio asset included in the package |
| `spawnEffect` | Creates a controlled local visual effect |
| `branch` | Selects a branch based on an allowed context field |
| `random` | Selects one child node by weight |
| `loop` | Repeats with an explicit limit |
| `finish` | Explicitly completes the action |

## 9.3 Expressly Prohibited Nodes

```text
executeCode
shell
openApplication
openUrl
networkRequest
readFile
writeFile
clipboard
screenCapture
keyboardInput
mouseControl
invokeCodex
```

Any unknown node type MUST cause validation of that action to fail.

## 9.4 Complex Action Example

```json
{
  "id": "graph.throw-paper",
  "root": {
    "type": "sequence",
    "children": [
      {
        "type": "playClip",
        "clip": "clip.notice-document",
        "await": "complete"
      },
      {
        "type": "parallel",
        "children": [
          {
            "type": "playClip",
            "clip": "clip.run",
            "loopUntil": "movement.run1.completed"
          },
          {
            "type": "movePet",
            "id": "movement.run1",
            "target": {
              "type": "screenNormalized",
              "x": 0.75,
              "y": 0.85
            },
            "durationMs": 900,
            "easing": "ease-in-out"
          }
        ]
      },
      {
        "type": "playClip",
        "clip": "clip.throw-paper",
        "awaitMarker": "release"
      },
      {
        "type": "playSound",
        "asset": "audio/paper-throw.ogg",
        "volume": 0.7
      },
      {
        "type": "finish",
        "result": "success"
      }
    ]
  }
}
```

## 9.5 Runtime Constraints

- A `loop` MUST set `maxIterations` or `maxDurationMs`.
- A `parallel` node MUST declare one completion policy: `all`, `any`, or `firstFailure`.
- A `branch` may read only normalized context fields permitted by PPAS.
- An action graph MUST NOT read raw system-event payloads.
- One action graph MUST NOT exceed 256 nodes.
- Nesting depth MUST NOT exceed 16.
- When the action's maximum duration is reached, the host MUST terminate it and execute its fallback.

## 9.6 Permitted Action Context

```text
context.platform
context.triggerId
context.triggerCategory
context.pet.facing
context.pet.scale
context.pet.screenEdge
context.task.status
context.task.progress
context.randomBucket
```

File names, paths, window titles, clipboard contents, keyboard input, and screen contents MUST NOT enter the action context.

---

# 10. Trigger Model

## 10.1 Basic Semantics

A trigger means:

```text
when an event occurs,
and the declared conditions are satisfied,
after permission and frequency controls pass,
execute an action.
```

A trigger may use only Event Providers supplied by PipiPong and MUST NOT include custom listener code.

## 10.2 Trigger Structure

```json
{
  "id": "trigger.vscode-foreground",
  "nameKey": "trigger.vscodeForeground.name",
  "descriptionKey": "trigger.vscodeForeground.description",
  "enabledByDefault": true,
  "capabilityRefs": ["cap.vscode-foreground"],
  "when": {
    "provider": "application.foreground",
    "event": "entered"
  },
  "match": {
    "resourceRefs": ["app.vscode"]
  },
  "conditions": {
    "all": []
  },
  "then": {
    "action": "custom.start-coding",
    "mode": "replaceAmbient",
    "priority": 50
  },
  "debounceMs": 500,
  "cooldownMs": 3000,
  "probability": 1.0,
  "maxRunsPerHour": 30,
  "onUnavailable": "disableTrigger"
}
```

## 10.3 Trigger Modes

`then.mode` supports:

| Mode | Meaning |
|---|---|
| `enqueue` | Execute after the current action finishes |
| `replaceAmbient` | Replace only a low-priority idle or ambient action |
| `beforeCore` | Execute before the corresponding core feedback action |
| `afterCore` | Execute after the corresponding core feedback action |
| `parallelVisual` | Run concurrently only as a non-conflicting visual effect |
| `randomAlternative` | Probabilistically replace a non-safety core action that is eligible for replacement |

A pet package MUST NOT replace safety confirmations, permission prompts, deletion confirmations, critical errors, or feedback for direct user operations.

## 10.4 Condition Operators

v0.9.5 supports:

```text
eq
neq
lt
lte
gt
gte
in
notIn
between
changedTo
```

String matching is permitted only for fixed enumerations approved by the host or for package-internal resource IDs. Matching against sensitive fields such as file names or window titles MUST occur within the host, and the original string MUST NOT be passed to the pet runtime.

Condition composition supports:

```text
all
any
not
```

The maximum composition nesting depth is four.

## 10.5 Frequency and Anti-Disruption Controls

Each trigger MUST support configuration of:

- `debounceMs`: event-debounce interval;
- `cooldownMs`: cooldown after firing;
- `probability`: value from 0 to 1;
- `maxRunsPerHour`: maximum runs per hour;
- `maxRunsPerDay`: optional daily limit; and
- `enabledByDefault`: whether the trigger is enabled immediately after installation.

The host MAY further reduce trigger frequency under global do-not-disturb controls, but it MUST NOT increase the frequency declared by the package.

---

# 11. v0.9.5 Event Provider Catalog

## 11.1 PipiPong and User-Interaction Events

These events do not require additional system-observation permissions, but they MUST remain visible to the user in the trigger list.

### `pet.interaction`

```text
clicked
doubleClicked
longPressed
hoverStarted
hoverEnded
dragStarted
dragEnded
dropped
```

### `pipipong.task`

```text
started
thinkingStarted
executionStarted
progressChanged
completed
failed
cancelled
```

### `pipipong.voice`

```text
listeningStarted
listeningEnded
transcriptReady
```

## 11.2 System Events Without Sensitive Payloads

### `time.schedule`

Used for fixed times, day-of-week rules, and periodic triggers.

```text
matched
```

Permitted conditions:

```text
daysOfWeek
localTimeRange
intervalMinutes
```

### `system.power`

```text
batteryLevelChanged
chargingStarted
chargingStopped
lowPowerEntered
lowPowerExited
```

Permitted normalized fields:

```text
battery.levelPercent
battery.charging
```

### `system.session`

```text
locked
unlocked
sleeping
woke
```

### `system.network`

```text
online
offline
```

The provider MUST NOT inspect network traffic, domains, message content, or connection lists.

### `display.configuration`

```text
displayConnected
displayDisconnected
primaryDisplayChanged
```

The provider MUST NOT inspect screen content.

## 11.3 System Events Requiring Explicit Per-Package Authorization

### `system.idle`

```text
thresholdReached
activityResumed
```

Permitted field:

```text
idle.durationSeconds
```

The package MUST declare a specific threshold and MUST NOT receive a continuous high-frequency stream of raw activity data.

### `application.lifecycle`

```text
launched
terminated
```

Only the explicitly declared set of applications may be observed.

### `application.foreground`

```text
entered
left
```

The provider may determine only whether a declared application entered or left the foreground. It MUST NOT read window body content, document content, or keyboard input.

An application resource may be declared as follows:

```json
{
  "id": "app.vscode",
  "type": "application",
  "matchers": {
    "macos": {
      "bundleIds": ["com.microsoft.VSCode"]
    },
    "windows": {
      "processNames": ["Code.exe"],
      "appUserModelIds": []
    }
  },
  "displayName": "Visual Studio Code"
}
```

### `filesystem.watch`

v0.9.5 permits observation only of a directory that the user actively selects in the authorization interface.

Supported events:

```text
fileCreated
fileRenamed
fileDeleted
fileModified
```

Only `fileCreated` SHOULD be exposed by default.

Permitted filters:

```text
fileExtensions
restrictedGlob
recursive
settleMs
```

Constraints:

- file contents MUST NOT be read;
- real paths and file names MUST NOT be passed to the animation runtime;
- the creator MUST NOT hard-code the user's home directory, Desktop, or an entire disk;
- `restrictedGlob` permits only simple glob syntax and not regular expressions;
- after local filtering, the host sends only `trigger.matched`; and
- directory permission MUST be bound to an opaque token created after user selection.

### `media.playback` (Platform Optional)

```text
started
paused
stopped
```

v0.9.5 MAY mark this provider as platform-optional. If the current platform does not support it, dependent triggers MUST be disabled with a user-readable explanation and MUST NOT cause the package or application to crash.

## 11.4 Providers Explicitly Prohibited in v0.9.5

```text
keyboard.global
clipboard.content
screen.content
camera
microphone.background
window.content
window.title.raw
browser.history
browser.cookies
file.content
shell
process.inject
network.traffic
```

---

# 12. System Capability and Permission Declarations

## 12.1 Permission Categories

`capabilities.json` MUST divide capabilities into three categories:

1. `declarations`: capabilities that must be disclosed but do not require an additional per-package authorization action;
2. `required`: capabilities whose refusal prevents full package activation; and
3. `optional`: capabilities whose refusal disables only the dependent triggers.

Every computer-system event capability MUST be disclosed before download, whether or not the operating system itself displays a permission dialog.

## 12.2 `capabilities.json` Example

```json
{
  "resources": [
    {
      "id": "app.vscode",
      "type": "application",
      "displayName": "Visual Studio Code",
      "matchers": {
        "macos": { "bundleIds": ["com.microsoft.VSCode"] },
        "windows": { "processNames": ["Code.exe"] }
      }
    },
    {
      "id": "dir.pdf-inbox",
      "type": "userSelectedDirectory",
      "labelKey": "resource.pdfInbox.label"
    }
  ],
  "declarations": [
    {
      "id": "cap.power-status",
      "capability": "system.power.observe",
      "purposeKey": "capability.power.purpose",
      "dataLevel": "statusOnly",
      "retention": "none",
      "networkTransmission": "none"
    }
  ],
  "required": [
    {
      "id": "cap.vscode-foreground",
      "capability": "application.foreground.observe",
      "resourceRefs": ["app.vscode"],
      "purposeKey": "capability.vscode.purpose",
      "dataLevel": "hostFilteredMatchOnly",
      "retention": "none",
      "networkTransmission": "none",
      "onDenied": "disablePackage"
    }
  ],
  "optional": [
    {
      "id": "cap.pdf-inbox",
      "capability": "filesystem.directoryChanges.observe",
      "resourceRefs": ["dir.pdf-inbox"],
      "allowedEvents": ["fileCreated"],
      "filters": {
        "fileExtensions": ["pdf"],
        "recursive": false,
        "settleMs": 1500
      },
      "purposeKey": "capability.pdfInbox.purpose",
      "dataLevel": "hostFilteredMatchOnly",
      "retention": "none",
      "networkTransmission": "none",
      "onDenied": "disableDependentTriggers"
    }
  ]
}
```

## 12.3 Mandatory Declaration Fields

Every capability declaration MUST explain:

| Field | Meaning |
|---|---|
| `capability` | The requested system-observation capability |
| `resourceRefs` | The specific application, directory, or other resource scope |
| `purposeKey` | A plain-language explanation of why the capability is needed |
| `dataLevel` | The granularity inspected by the host |
| `retention` | Whether raw data is retained |
| `networkTransmission` | Whether data leaves the device; in v0.9.5 this MUST be `none` |
| `onDenied` | Behavior after the user refuses the capability |

Statements such as “to improve the experience” or “to provide full functionality” are not valid purpose explanations. The purpose MUST describe the concrete trigger and resulting action, for example:

> When Visual Studio Code enters the foreground, the pet puts on glasses and starts typing.

## 12.4 Preconditions for Download and Enablement

### Marketplace Download

Before the download control, the PipiPong marketplace MUST display a host-generated summary derived from the machine-readable declarations:

```text
This pet package requires:

Required
• Determine whether Visual Studio Code enters the foreground
  Purpose: play the “start coding” action when a coding application is opened
  Data: match status only; no window content is read
  Retention: none
  Upload: none

Optional
• Observe newly created PDF files in one folder you select
  Purpose: play the “pick up file” action when a new PDF appears
  Data: PipiPong matches locally; the pet receives only “condition matched”
  Retention: none
  Upload: none
```

The user MUST acknowledge that these conditions have been reviewed before the download begins.

### Enablement

The user MUST explicitly accept every `required` capability before the package can be activated.

Permitted controls are:

```text
[Allow and Enable]
[Enable Basic Mode Only]  only if the package declares a functional degraded mode
[Cancel]
```

For a locally imported package, the host MAY read the manifest for preflight analysis, but MUST NOT start a watcher, play an automatically triggered action, or access a system Event Provider before authorization.

## 12.5 Per-Package Virtual Permissions

Operating systems normally recognize that PipiPong holds a permission, not which individual pet package requested it. PipiPong MUST therefore enforce per-package isolation:

```text
OS Permission
  └─ PipiPong Permission Broker
       ├─ Package A: may observe VS Code foreground status
       ├─ Package B: has no application-observation permission
       └─ Package C: may observe a user-selected PDF directory
```

A grant MUST be bound to at least:

```text
packageId
packageVersion
capabilityId
resourceScope
grantState
grantedAt
```

A package MUST NOT inherit another package's grants.

## 12.6 Host-Side Filtering

Raw system information MUST NOT enter the pet renderer process.

Required flow:

```text
Raw system event
→ PipiPong Provider
→ permission and scope check
→ local condition matching
→ send only triggerId and minimal normalized context
→ execute action
```

The action runtime may receive:

```json
{
  "event": "trigger.matched",
  "triggerId": "trigger.vscode-foreground",
  "category": "application.foreground"
}
```

It MUST NOT receive:

```text
full window titles
real file paths
file-name lists
application-usage history
keyboard input
clipboard contents
```

---

# 13. Permission Updates and Revocation

## 13.1 Package Updates

When updating a package, the host MUST compare the old and new capability declarations.

| Change | Required handling |
|---|---|
| Only animations are added or assets are corrected | Update normally |
| A permission is removed | Automatically stop and remove watchers that are no longer needed |
| An optional permission is added | Keep it disabled until the user explicitly enables it |
| A required permission is added | Suspend activation of the new version and request renewed consent |
| Application or directory scope is expanded | Treat as a new permission and request renewed consent |
| Data granularity is increased | Request renewed consent |
| The purpose explanation changes | Request renewed consent when the change is substantive |

A package MUST NOT evade scope-difference detection by preserving an old capability ID while changing its scope.

## 13.2 User Revocation

The user MUST be able to open:

```text
Settings → Appearance → Current Pet → Permissions and Triggers
```

and:

- revoke an individual permission;
- disable an individual trigger;
- replace a user-selected directory;
- review recent trigger records;
- restore default settings; and
- disable all system-observation capabilities for the package.

When a permission is revoked, the corresponding watcher MUST stop immediately and dependent triggers MUST be shown as unavailable.

---

# 14. Data and Privacy Rules

## 14.1 Fixed v0.9.5 Requirements

Every PPAS v0.9.5 package MUST satisfy:

```json
{
  "localProcessingOnly": true,
  "networkTransmission": "none",
  "rawEventStorage": "none"
}
```

A pet package MUST NOT declare any other value.

## 14.2 Host State That May Be Stored

PipiPong MAY store only the following minimal state:

- whether the user enabled a capability;
- the opaque token for a user-selected resource;
- whether a trigger is enabled;
- cooldown timestamps;
- hourly or daily execution counters; and
- the selected pet package and version.

PipiPong MUST NOT store:

- file-name history;
- full-path history;
- an application-usage timeline;
- window titles;
- screen contents; or
- a raw system-event stream.

## 14.3 Logging

Debug logs MUST be redacted by default. Permitted log records include:

```text
trigger.vscode-foreground matched
custom.start-coding started
custom.start-coding completed
```

Prohibited log records include:

```text
The user opened /Users/name/SecretProject/ClientA.pdf
The window title was Confidential Acquisition.docx
```

---
# 15. Action Scheduling, Priority, and Interruption

## 15.1 Host Priority Bands

PipiPong MUST use the following priority bands:

| Priority | Category |
|---:|---|
| 100 | Safety prompts, critical errors, and application exit |
| 90 | Direct user operations, including dragging and confirmation clicks |
| 80 | Voice-listening and recording feedback |
| 70 | Core task feedback, including start, work, success, and failure |
| 40–60 | User-enabled system triggers and custom actions |
| 20–39 | Random personality actions and ambient actions |
| 10–19 | Idle and other low-priority standby behavior |

A package-defined `priority` may be only in the range 10–60.

## 15.2 Interruption Policies

Supported policies are:

- `immediate`: the action may be switched immediately;
- `atMarker`: switch when a declared safe marker is reached; and
- `afterIteration`: switch after the current loop iteration completes.

Regardless of the package declaration, the host MAY terminate an action immediately in any of the following situations:

- a safety confirmation is required;
- a permission prompt is required;
- the application is exiting;
- the pet package or renderer crashes;
- the user begins dragging the pet;
- maximum runtime is exceeded; or
- a resource-use limit is exceeded.

## 15.3 Scheduling Rules

- only one principal action may control the pet body at a time;
- `parallelVisual` may be used only for effects that do not alter the principal action state;
- a higher-priority action may preempt a lower-priority action;
- a preempted action is cancelled by default and is not resumed automatically unless the host explicitly supports resume semantics;
- repeated trigger events MUST be subject to debounce and cooldown controls;
- an action failure MUST invoke its fallback;
- if the fallback fails, the runtime MUST return to a built-in safe idle action; and
- a package MUST NOT prevent the user from closing, dragging, or disabling the pet.

---

# 16. Security Model

## 16.1 Packages Are Untrusted Input

Every third-party package MUST be processed as untrusted input.

## 16.2 Prohibited Content

The importer MUST reject:

```text
.exe .dll .dylib .so .node .app .bat .cmd .ps1 .sh
.js .mjs .cjs .ts .py .lua .wasm
macros, scripted SVG, external URLs, remote fonts, remote images
symbolic links, path traversal, encrypted archives, ZIP bombs
```

## 16.3 Electron Runtime Boundary

The pet renderer process MUST be configured with:

```text
nodeIntegration: false
contextIsolation: true
sandbox: true
```

General-purpose IPC, file paths, Shell access, network access, and Node.js APIs MUST NOT be exposed to the pet renderer process.

The preload bridge may expose only an allowlist of capabilities, for example:

```text
pet.playClip
pet.move
pet.transform
pet.playSound
pet.spawnEffect
pet.reportActionResult
```

## 16.4 Safe Host Capabilities

A v0.9.5 action graph may request only:

```text
pet.window.move
pet.window.transform
pet.window.flip
audio.local.play
effect.local.spawn
```

The main process MUST still validate every request's parameters, scope, and frequency.

---

# 17. Installation and Validation Flow

## 17.1 Validation Stages

### L0: Container Validation

- valid ZIP structure;
- safe paths;
- file-count and size limits;
- prohibited-file checks;
- no symbolic links; and
- ZIP-bomb protection.

### L1: JSON Schema Validation

The implementation MUST provide and use:

```text
manifest.schema.json
animations.schema.json
core-actions.schema.json
custom-actions.schema.json
action-graph.schema.json
triggers.schema.json
capabilities.schema.json
integrity.schema.json
```

### L2: Semantic Validation

- all mandatory core actions exist;
- every referenced clip, action graph, audio asset, and effect exists;
- every fallback exists and no infinite fallback cycle is possible;
- every capability referenced by a trigger exists;
- trigger scope does not exceed capability scope;
- every required extension is available;
- all IDs are unique;
- every loop has an explicit termination bound;
- every action graph can terminate or declares a maximum duration; and
- platform matcher formats are valid.

### L3: Asset Validation

- images can be decoded;
- alpha-channel and dimension metadata are valid;
- audio can be decoded;
- frame durations and aggregate durations are valid; and
- the package does not obviously exceed its memory budget.

### L4: Permission Preflight

- generate a user-readable permission summary;
- determine whether the current platform supports the requested providers;
- determine whether required capabilities can be requested; and
- verify that data-practice declarations satisfy the fixed v0.9.5 rules.

### L5: Sandboxed Smoke Test

- play each of the eight mandatory core actions;
- optionally play the Core Standard actions;
- execute every custom action in test mode;
- simulate `trigger.matched`;
- verify timeout, cancellation, and fallback behavior; and
- do not start real system watchers.

## 17.2 Result States

```text
VALID
VALID_WITH_WARNINGS
INCOMPATIBLE
BLOCKED_UNSAFE
PERMISSION_REQUIRED
```

## 17.3 Common Error Codes

```text
PPAS_E_ARCHIVE_INVALID
PPAS_E_PATH_TRAVERSAL
PPAS_E_SIZE_LIMIT
PPAS_E_FORBIDDEN_FILE
PPAS_E_SCHEMA_INVALID
PPAS_E_MISSING_CORE_ACTION
PPAS_E_ASSET_MISSING
PPAS_E_ACTION_GRAPH_INVALID
PPAS_E_TRIGGER_SCOPE_EXCEEDS_CAPABILITY
PPAS_E_CAPABILITY_UNSUPPORTED
PPAS_E_PERMISSION_DENIED
PPAS_E_EXTENSION_UNSUPPORTED
PPAS_E_RUNTIME_TIMEOUT
PPAS_E_RENDERER_CRASH
PPAS_E_INTEGRITY_MISMATCH
```

Every error MUST include both a machine-readable code and a user-readable explanation.

---

# 18. Package Integrity, Signing, and Version Rollback

## 18.1 `integrity.json`

```json
{
  "algorithm": "sha256",
  "files": {
    "manifest.json": "<sha256>",
    "animations/index.json": "<sha256>",
    "actions/core.json": "<sha256>"
  },
  "signature": {
    "status": "unsigned"
  }
}
```

A local package MAY be unsigned, but the client MUST display “Unverified local pet package.”

A marketplace package MUST:

- pass server-side static scanning;
- use SHA-256;
- carry a platform signature;
- record publisher, version, and review status;
- be verified again after download; and
- support revocation of a problematic version.

## 18.2 Installation Directory

Content-addressed storage is recommended:

```text
pets/
  <packageId>/
    <packageVersion>/
      <contentHash>/
```

During an update, at least one rollback-capable version MUST be retained until the new version completes validation and first launch successfully.

---

# 19. Creator Workflow

## 19.1 Settings Entry Point

PipiPong v0.9.5 SHOULD provide PPAS creation and import under:

```text
Settings → Appearance → Hatch a New Desktop Pet
```

## 19.2 Official Hatching Workflow

The official hatching tool MUST:

1. obtain or generate the pet's base appearance;
2. generate the ten Core Standard actions;
3. normalize canvas size, transparent background, anchor, and dimensions;
4. generate `animations/index.json`;
5. generate core-action bindings;
6. allow the user to preview and regenerate an individual action;
7. produce a baseline `.pppet` package with no system permissions; and
8. install the package only after it passes the PPAS Validator.

The interface SHOULD NOT emphasize whether Codex is used internally.

## 19.3 Custom-Action Editing

The v0.9.5 Pet Package Builder SHOULD provide at least:

- frame-sequence import;
- action name and description editing;
- one-shot or looping configuration;
- frame-rate or per-frame duration editing;
- anchor editing;
- marker creation;
- action priority and interruption-policy configuration;
- composition of clips, movement, waits, audio, and effects into a complex action;
- action preview; and
- testing of cancellation, timeout, and fallback behavior.

Users SHOULD NOT be required to author JSON manually. An advanced mode MAY display and export JSON.

## 19.4 Trigger Editing

The Builder MUST use a form-based interface rather than code:

```text
When: [Visual Studio Code enters the foreground]
Conditions: [None]
Action: [Start typing]
Probability: [100%]
Cooldown: [3 seconds]
Permission: [Required / Optional]
Purpose: [When a coding application enters the foreground, the pet starts working]
```

For directory events:

```text
Observation scope: [The downloader selects one folder]
Event: [New file]
File type: [PDF]
Recursive: [No]
```

The Builder MUST show, in real time, the exact permission-disclosure card that an end user will see.

## 19.5 Test Mode

The Builder MUST provide simulated events, including:

```text
Simulate low battery
Simulate VS Code entering the foreground
Simulate a new PDF appearing
Simulate task completion
Simulate three consecutive clicks
```

Test mode MUST NOT scan the user's computer or start a real system watcher.

---

# 20. End-User Management Interface

Each installed package MUST have a details page that displays at least:

- name, author, version, and license;
- Core Minimum / Core Standard compatibility status;
- previews of all core actions;
- a list of custom actions;
- a list of system-event triggers;
- required, optional, and declaration-only capabilities;
- the data scope, purpose, retention, and transmission statement for each capability;
- current authorization status;
- an enable/disable control for each trigger;
- recent trigger records that contain no sensitive raw values;
- permission differences introduced by an update;
- a one-click return to basic mode; and
- uninstall and cleanup controls.

---

# 21. Cross-Platform Behavior

## 21.1 Platform Support Declaration

A package MUST declare:

```json
{
  "platforms": ["macos", "windows"]
}
```

If a custom trigger supports only one platform, that trigger MUST declare it separately:

```json
{
  "platforms": ["windows"]
}
```

## 21.2 Handling Unsupported Capabilities

- an optional trigger MUST be disabled with an explanation;
- if a required capability is unavailable, the package cannot be fully enabled on that platform;
- if the package declares a degraded mode, core actions MAY still be enabled;
- absence of one optional provider MUST NOT crash the application; and
- the host MUST NOT guess that a macOS identifier is valid on Windows or vice versa.

---

# 22. Recommended Runtime Interfaces

The following TypeScript interfaces are implementation guidance. Field placement may be adjusted to fit the existing repository, but their semantics MUST NOT be weakened.

```ts
export interface PPASManifest {
  ppasVersion: "0.9.5";
  packageId: string;
  packageVersion: string;
  defaultLocale: string;
  nameKey: string;
  descriptionKey: string;
  author: {
    name: string;
    creatorId?: string;
  };
  license: string;
  compatibility: {
    minAppVersion: string;
    platforms: Array<"macos" | "windows">;
    requiredRendererProfiles: string[];
  };
  coreProfile: "PPAS-Core-Minimum-0.9.5" | "PPAS-Core-Standard-0.9.5";
  entryPoints: {
    animations: string;
    coreActions: string;
    customActions: string;
    triggers: string;
    capabilities: string;
  };
}
```

```ts
export interface PetActionRuntime {
  play(actionId: string, context: SafeActionContext): Promise<ActionResult>;
  cancel(reason: ActionCancelReason): Promise<void>;
  listActions(): PetActionDescriptor[];
  validateAction(actionId: string): ActionValidationResult;
}
```

```ts
export interface SystemEventProvider {
  readonly id: string;
  isSupported(): Promise<boolean>;
  requestHostPermission(scope: ProviderScope): Promise<HostPermissionResult>;
  subscribe(
    grant: PackagePermissionGrant,
    filter: HostSideFilter,
    onMatched: (event: SanitizedMatchedEvent) => void
  ): Promise<Unsubscribe>;
}
```

```ts
export interface PackagePermissionBroker {
  preflight(packageId: string, capabilities: CapabilityManifest): Promise<ConsentSummary>;
  grant(request: CapabilityGrantRequest): Promise<PackagePermissionGrant>;
  revoke(packageId: string, capabilityId: string): Promise<void>;
  diff(oldManifest: CapabilityManifest, nextManifest: CapabilityManifest): PermissionDiff;
}
```

---

# 23. Complete Examples of System-Triggered Actions

## 23.1 VS Code Enters the Foreground

Capability declaration:

```json
{
  "id": "cap.vscode-foreground",
  "capability": "application.foreground.observe",
  "resourceRefs": ["app.vscode"],
  "purposeKey": "capability.vscode.purpose",
  "dataLevel": "hostFilteredMatchOnly",
  "retention": "none",
  "networkTransmission": "none",
  "onDenied": "disablePackage"
}
```

Trigger:

```json
{
  "id": "trigger.vscode-foreground",
  "capabilityRefs": ["cap.vscode-foreground"],
  "when": {
    "provider": "application.foreground",
    "event": "entered"
  },
  "match": {
    "resourceRefs": ["app.vscode"]
  },
  "then": {
    "action": "custom.start-coding",
    "mode": "replaceAmbient",
    "priority": 50
  },
  "cooldownMs": 3000,
  "maxRunsPerHour": 30
}
```

## 23.2 Low Battery

```json
{
  "id": "trigger.low-battery",
  "capabilityRefs": ["cap.power-status"],
  "when": {
    "provider": "system.power",
    "event": "batteryLevelChanged"
  },
  "conditions": {
    "all": [
      {
        "field": "battery.levelPercent",
        "operator": "lte",
        "value": 20
      },
      {
        "field": "battery.charging",
        "operator": "eq",
        "value": false
      }
    ]
  },
  "then": {
    "action": "custom.hungry",
    "mode": "replaceAmbient",
    "priority": 45
  },
  "cooldownMs": 1800000,
  "maxRunsPerDay": 6
}
```

## 23.3 A PDF Appears in a User-Selected Directory

Capability declaration:

```json
{
  "id": "cap.pdf-inbox",
  "capability": "filesystem.directoryChanges.observe",
  "resourceRefs": ["dir.pdf-inbox"],
  "allowedEvents": ["fileCreated"],
  "filters": {
    "fileExtensions": ["pdf"],
    "recursive": false,
    "settleMs": 1500
  },
  "purposeKey": "capability.pdfInbox.purpose",
  "dataLevel": "hostFilteredMatchOnly",
  "retention": "none",
  "networkTransmission": "none",
  "onDenied": "disableDependentTriggers"
}
```

Trigger:

```json
{
  "id": "trigger.new-pdf",
  "capabilityRefs": ["cap.pdf-inbox"],
  "when": {
    "provider": "filesystem.watch",
    "event": "fileCreated"
  },
  "match": {
    "resourceRefs": ["dir.pdf-inbox"]
  },
  "then": {
    "action": "custom.pick-up-document",
    "mode": "enqueue",
    "priority": 45
  },
  "debounceMs": 1500,
  "cooldownMs": 10000,
  "maxRunsPerHour": 12
}
```

The pet animation receives only:

```json
{
  "event": "trigger.matched",
  "triggerId": "trigger.new-pdf",
  "category": "filesystem.watch"
}
```

It MUST NOT receive the PDF file name or the real directory path.

---

# 24. v0.9.5 Implementation Modules

Codex SHOULD split the PPAS implementation into the following modules so that system permissions, rendering, and package parsing do not become coupled.

## 24.1 Shared

```text
src/shared/ppas/
  types/
  schemas/
  constants/
  error-codes/
  versioning/
```

Responsibilities:

- shared types;
- JSON Schemas;
- Core Action constants;
- Provider and Capability constants;
- unified error codes; and
- version comparison and permission-diff logic.

## 24.2 Main Process

```text
src/main/pet-packages/
  archive-validator/
  semantic-validator/
  installer/
  integrity/
  package-store/

src/main/system-events/
  provider-registry/
  macos/
  windows/
  host-filter/

src/main/permissions/
  package-permission-broker/
  consent-summary/
  grant-store/
```

Responsibilities:

- extraction and security validation;
- installation and rollback;
- system-event observation;
- per-package permissions;
- host-side filtering; and
- watcher lifecycle management.

## 24.3 Renderer / Pet Runtime

```text
src/renderer/pet-runtime/
  sprite-renderer/
  action-runtime/
  action-scheduler/
  trigger-client/
  safe-host-bridge/
  fallback-pet/
```

Responsibilities:

- frame-sequence playback;
- action-graph execution;
- priority, queueing, and cancellation;
- receipt of filtered `trigger.matched` events; and
- no direct access to system APIs.

## 24.4 Settings / Builder

```text
src/renderer/settings/pet-packages/
  package-library/
  package-details/
  action-preview/
  permissions-and-triggers/
  package-import/
  package-update-diff/

src/renderer/pet-builder/
  core-action-generator/
  clip-editor/
  action-composer/
  trigger-editor/
  consent-preview/
  validator-report/
  exporter/
```

---

# 25. Acceptance Criteria

## 25.1 Package Format

- a valid `.pppet` package can be imported;
- path traversal, scripts, oversized resources, and hash mismatches are rejected;
- a package missing any Core Minimum action cannot be enabled;
- a Minimum package without `wake` or `sleep` can use the defined fallbacks; and
- if an update fails, the previous version can be restored.

## 25.2 Animation and Actions

- all eight mandatory core actions can be previewed independently;
- an officially hatched package contains ten actions by default;
- a custom clip action can execute;
- `sequence`, `parallel`, movement, wait, audio, branch, random, and loop behavior can execute;
- infinite loops and timed-out actions are terminated;
- action failure returns to the declared fallback; and
- safety prompts and user dragging can preempt package actions.

## 25.3 Triggers

- no watcher starts before authorization;
- refusal of a required capability prevents full activation;
- refusal of an optional capability disables only dependent triggers;
- a trigger cannot exceed its capability scope;
- debounce, cooldown, probability, and execution limits work;
- an unsupported platform provider degrades correctly; and
- the user can disable each trigger individually.

## 25.4 Privacy

- the animation process cannot obtain file paths, file names, window titles, or application history;
- a directory trigger sends only `triggerId`;
- a package cannot initiate a network request;
- a package cannot access Node.js, Shell, clipboard, screen, camera, or microphone capabilities;
- logs contain no sensitive raw values; and
- a watcher stops immediately after permission revocation.

## 25.5 Updates

- a newly added optional permission is disabled by default;
- a newly added required permission prevents automatic activation and requests renewed consent;
- scope expansion is detected as a permission change;
- permission removal cleans up watchers and grants; and
- the user can inspect the old-to-new permission difference.

## 25.6 Cross-Platform

- macOS and Windows use the same PPAS package structure;
- application identity uses platform-specific matchers;
- an unavailable platform capability does not cause a crash;
- existing macOS security boundaries are not weakened for Windows compatibility; and
- the Windows implementation does not use arbitrary UI automation to bypass the PPAS permission model.

---

# 26. Test Matrix

At minimum, testing MUST cover:

| Test type | Scenario |
|---|---|
| Schema | Missing fields, incorrect types, unknown required extension |
| Archive | Path traversal, ZIP bomb, symbolic link, prohibited file |
| Core Actions | Omission of each mandatory action in turn |
| Graph | Infinite loop, excess depth, unknown node, fallback cycle |
| Permission | Required denial, optional denial, revocation, scope expansion |
| Provider | Application launch/termination, foreground changes, idle, battery, directory event |
| Privacy | Verify that the renderer does not receive raw events |
| Scheduler | High-priority preemption, marker interruption, cooldown, queueing |
| Update | No capability change, new capability, expanded scope, version rollback |
| Platform | macOS and Windows identifiers and unavailable providers |
| Recovery | Renderer crash, damaged asset, action timeout, application restart |

All critical security tests MUST run in CI.

---

# 27. Definition of Done for v0.9.5

PPAS v0.9.5 is complete only when all of the following are true:

1. the package structure, JSON Schemas, and error codes are stable;
2. all eight Core Minimum actions execute correctly;
3. the official hatching workflow outputs ten Core Standard actions;
4. custom clips and Action Graphs execute correctly;
5. unified provider interfaces exist for at least `system.power`, `system.session`, `system.idle`, `application.lifecycle`, `application.foreground`, and `filesystem.watch`;
6. macOS and Windows both enforce per-package permissions;
7. system events pass through host-side filtering;
8. required and optional conditions are disclosed before download and enablement;
9. permission changes introduced by an update trigger renewed consent;
10. a third-party package cannot execute arbitrary code or directly access the computer;
11. Settings supports action preview, permission management, and trigger disabling; and
12. security, permission, and cross-platform tests run in CI.

---

# 28. Future Compatibility Directions (Not Mandatory in v0.9.5)

Future versions may add the following through extensions:

```text
PPAS_rive_renderer
PPAS_dotlottie_renderer
PPAS_spine_renderer
PPAS_live2d_renderer
PPAS_lip_sync
PPAS_accessory_slots
PPAS_multi_pet
PPAS_physics
PPAS_marketplace_signature
PPAS_creator_revenue
```

A future extension MUST NOT alter the following foundational principles:

- core actions use semantic IDs;
- system-observation capabilities are declared in advance;
- authorization is granted per package;
- raw information is filtered by the host;
- an ordinary pet package cannot execute arbitrary code; and
- the animation runtime cannot directly access system resources.

---

# 29. Final Architecture Decision

The formal technical architecture of PPAS v0.9.5 is:

```text
.pppet ZIP container
+ 8 mandatory / 10 official-standard core actions
+ sprite-sequence-v1
+ custom clips and declarative Action Graphs
+ PipiPong / user / computer-system Event Providers
+ required / optional Capability Manifest
+ disclosure before download and consent before enablement
+ per-package virtual permissions
+ host-side filtering
+ action scheduling, interruption, timeout, and fallback
+ strict sandboxing and fail-closed validation
```

This model gives creators the freedom to build pets with a complete personality, complex actions, and reactions to real computer-context events, while ensuring that downloaders know—before use—what the package will observe, why it will observe it, at what level of granularity, and what happens if authorization is refused.
