From 40012f3aed764e95fc8915b944429ff0facaf34c Mon Sep 17 00:00:00 2001 From: Damian Reeves <957246+DamianReeves@users.noreply.github.com> Date: Tue, 20 Jan 2026 09:06:10 -0600 Subject: [PATCH] chore: introduce beads issue tracking with IR v4 implementation plan - Add beads workflow for local issue tracking and session management - Create epic for Morphir IR v4 implementation (morphir-python-3a9) - Add 12 child tasks covering all IR v4 components: - Naming module (Name, Path, QName, FQName) - Types module (Type expressions, specs, definitions) - Values module (Literals, patterns, expressions) - Modules structure (Documentation, ModuleSpec/Def) - Packages structure (PackageSpec/Def) - Distributions (Library, Specs, Application) - Decorations system (layered metadata) - Document type (schema-less JSON-like data) - Meta and Refs ($meta, $ref support) - JSON serialization (shorthand + canonical formats) - VFS file I/O (discrete distribution mode) - Unit tests Reference specification: https://morphir.finos.org/docs/design/draft/ --- .beads/.gitignore | 39 +++++++++++++++++++ .beads/README.md | 81 +++++++++++++++++++++++++++++++++++++++ .beads/config.yaml | 62 ++++++++++++++++++++++++++++++ .beads/interactions.jsonl | 0 .beads/issues.jsonl | 13 +++++++ .beads/metadata.json | 4 ++ .gitattributes | 3 ++ AGENTS.md | 26 +++++++++++++ 8 files changed, 228 insertions(+) create mode 100644 .beads/.gitignore create mode 100644 .beads/README.md create mode 100644 .beads/config.yaml create mode 100644 .beads/interactions.jsonl create mode 100644 .beads/issues.jsonl create mode 100644 .beads/metadata.json create mode 100644 .gitattributes diff --git a/.beads/.gitignore b/.beads/.gitignore new file mode 100644 index 00000000..4a7a77df --- /dev/null +++ b/.beads/.gitignore @@ -0,0 +1,39 @@ +# SQLite databases +*.db +*.db?* +*.db-journal +*.db-wal +*.db-shm + +# Daemon runtime files +daemon.lock +daemon.log +daemon.pid +bd.sock +sync-state.json +last-touched + +# Local version tracking (prevents upgrade notification spam after git ops) +.local_version + +# Legacy database files +db.sqlite +bd.db + +# Worktree redirect file (contains relative path to main repo's .beads/) +# Must not be committed as paths would be wrong in other clones +redirect + +# Merge artifacts (temporary files from 3-way merge) +beads.base.jsonl +beads.base.meta.json +beads.left.jsonl +beads.left.meta.json +beads.right.jsonl +beads.right.meta.json + +# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here. +# They would override fork protection in .git/info/exclude, allowing +# contributors to accidentally commit upstream issue databases. +# The JSONL files (issues.jsonl, interactions.jsonl) and config files +# are tracked by git by default since no pattern above ignores them. diff --git a/.beads/README.md b/.beads/README.md new file mode 100644 index 00000000..50f281f0 --- /dev/null +++ b/.beads/README.md @@ -0,0 +1,81 @@ +# Beads - AI-Native Issue Tracking + +Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code. + +## What is Beads? + +Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git. + +**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads) + +## Quick Start + +### Essential Commands + +```bash +# Create new issues +bd create "Add user authentication" + +# View all issues +bd list + +# View issue details +bd show + +# Update issue status +bd update --status in_progress +bd update --status done + +# Sync with git remote +bd sync +``` + +### Working with Issues + +Issues in Beads are: +- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code +- **AI-friendly**: CLI-first design works perfectly with AI coding agents +- **Branch-aware**: Issues can follow your branch workflow +- **Always in sync**: Auto-syncs with your commits + +## Why Beads? + +✨ **AI-Native Design** +- Built specifically for AI-assisted development workflows +- CLI-first interface works seamlessly with AI coding agents +- No context switching to web UIs + +šŸš€ **Developer Focused** +- Issues live in your repo, right next to your code +- Works offline, syncs when you push +- Fast, lightweight, and stays out of your way + +šŸ”§ **Git Integration** +- Automatic sync with git commits +- Branch-aware issue tracking +- Intelligent JSONL merge resolution + +## Get Started with Beads + +Try Beads in your own projects: + +```bash +# Install Beads +curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash + +# Initialize in your repo +bd init + +# Create your first issue +bd create "Try out Beads" +``` + +## Learn More + +- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs) +- **Quick Start Guide**: Run `bd quickstart` +- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples) + +--- + +*Beads: Issue tracking that moves at the speed of thought* ⚔ diff --git a/.beads/config.yaml b/.beads/config.yaml new file mode 100644 index 00000000..f2427856 --- /dev/null +++ b/.beads/config.yaml @@ -0,0 +1,62 @@ +# Beads Configuration File +# This file configures default behavior for all bd commands in this repository +# All settings can also be set via environment variables (BD_* prefix) +# or overridden with command-line flags + +# Issue prefix for this repository (used by bd init) +# If not set, bd init will auto-detect from directory name +# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc. +# issue-prefix: "" + +# Use no-db mode: load from JSONL, no SQLite, write back after each command +# When true, bd will use .beads/issues.jsonl as the source of truth +# instead of SQLite database +# no-db: false + +# Disable daemon for RPC communication (forces direct database access) +# no-daemon: false + +# Disable auto-flush of database to JSONL after mutations +# no-auto-flush: false + +# Disable auto-import from JSONL when it's newer than database +# no-auto-import: false + +# Enable JSON output by default +# json: false + +# Default actor for audit trails (overridden by BD_ACTOR or --actor) +# actor: "" + +# Path to database (overridden by BEADS_DB or --db) +# db: "" + +# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON) +# auto-start-daemon: true + +# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE) +# flush-debounce: "5s" + +# Git branch for beads commits (bd sync will commit to this branch) +# IMPORTANT: Set this for team projects so all clones use the same sync branch. +# This setting persists across clones (unlike database config which is gitignored). +# Can also use BEADS_SYNC_BRANCH env var for local override. +# If not set, bd sync will require you to run 'bd config set sync.branch '. +# sync-branch: "beads-sync" + +# Multi-repo configuration (experimental - bd-307) +# Allows hydrating from multiple repositories and routing writes to the correct JSONL +# repos: +# primary: "." # Primary repo (where this database lives) +# additional: # Additional repos to hydrate from (read-only) +# - ~/beads-planning # Personal planning repo +# - ~/work-planning # Work planning repo + +# Integration settings (access with 'bd config get/set') +# These are stored in the database, not in this file: +# - jira.url +# - jira.project +# - linear.url +# - linear.api-key +# - github.org +# - github.repo diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl new file mode 100644 index 00000000..e69de29b diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl new file mode 100644 index 00000000..81b267b9 --- /dev/null +++ b/.beads/issues.jsonl @@ -0,0 +1,13 @@ +{"id":"morphir-python-1cq","title":"Implement IR v4 Distributions","description":"# Implement IR v4 Distributions\n\nImplement the distribution types for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/distributions.py`\n\n## Types to Implement\n\n### Distribution Variants\n- **Distribution[A]**: Union type of Library, Specs, or Application\n\n- **LibraryDistribution[A]**: Reusable package with implementations\n - `package: PackageInfo`\n - `definition: PackageDefinition[A]`\n - `dependencies: Dict[PackagePath, PackageSpecification[A]]`\n\n- **SpecsDistribution[A]**: Specifications only (no implementations)\n - Used for native/FFI bindings, SDK primitives, third-party APIs\n - `package: PackageInfo`\n - `specification: PackageSpecification[A]`\n - `dependencies: Dict[PackagePath, PackageSpecification[A]]`\n\n- **ApplicationDistribution[A]**: Executable with named entry points\n - `package: PackageInfo`\n - `definition: PackageDefinition[A]`\n - `dependencies: Dict[PackagePath, PackageDefinition[A]]` (full definitions - statically linked)\n - `entry_points: Dict[Name, EntryPoint]`\n\n### Entry Points\n- **EntryPoint**: Named entry into application\n - `target: FQName`\n - `kind: EntryPointKind`\n - `doc: Option[Documentation]`\n\n- **EntryPointKind**: Main, Command, Handler, Job, Policy\n\n### Package Info\n- **PackageInfo**: Package metadata\n - `name: PackagePath`\n - `version: SemanticVersion`\n\n### Semantic Versioning (SemVer 2.0.0)\n- **SemanticVersion**: MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]\n - `major: int`\n - `minor: int`\n - `patch: int`\n - `pre_release: Option[PreRelease]`\n - `build_metadata: Option[BuildMetadata]`\n\n- **PreRelease**: List of PreReleaseIdentifier\n- **PreReleaseIdentifier**: NumericIdentifier | AlphanumericIdentifier\n- **BuildMetadata**: List of strings\n\n### Distribution Modes\n- **DistributionMode**: ClassicMode | VfsMode\n- **VfsManifest**: format.json metadata\n- **VfsModuleManifest**: module.json metadata\n\n## JSON Serialization\n- Library distribution with `formatVersion: \"4.0.0\"`\n- Support both classic (single blob) and VFS (directory tree) modes\n- Semantic versions as canonical strings\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/distributions\n- finos/morphir repo: docs/design/draft/ir/distributions.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:45.122506562-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:45.122506562-06:00"} +{"id":"morphir-python-3a9","title":"Implement Morphir IR v4 in Python","description":"# Implement Morphir IR v4 in Python\n\nThis epic covers the complete implementation of the Morphir Intermediate Representation (IR) v4 specification in Python for the morphir-python project.\n\n## Overview\n\nThe Morphir IR v4 is the next-generation intermediate representation format that enables:\n- **VFS-Centric Architecture**: Distribution modeled as a hierarchical file system\n- **Polyglot Ecosystem**: Language-agnostic backends via JSON-RPC 2.0\n- **Dual Mode Support**: Both classic single-blob and discrete VFS file layouts\n- **Graceful Degradation**: Best-effort code generation during incremental refactoring\n\n## Reference Specification\n\n- **Primary Source**: https://morphir.finos.org/docs/design/draft/\n- **Reference Implementation**: finos/morphir repo (Gleam syntax)\n- **Version**: 4.0.0-draft (as of 2026-01-15)\n\n## Implementation Location\n\nThe IR types should be implemented in `packages/morphir/src/morphir/ir/` as the default IR (no version subfolder needed - prior IR versions can be namespaced if needed later).\n\n## Key Components\n\n1. **Naming Module** - Name, Path, QName, FQName types with canonical string format\n2. **Types Module** - Type expressions, specifications, and definitions\n3. **Values Module** - Literals, patterns, value expressions, and definitions\n4. **Modules** - Module structure, documentation wrapper\n5. **Packages** - Package specifications and definitions\n6. **Distributions** - Library, Specs, and Application distribution types\n7. **Decorations** - Layered metadata system for IR annotations\n8. **Document** - Schema-less JSON-like data type\n9. **Meta \u0026 Refs** - File-level metadata and node references\n\n## Design Principles\n\n- Use Python dataclasses or Pydantic for type definitions\n- Support both JSON serialization and programmatic construction\n- Follow canonical naming conventions (kebab-case with abbreviation support)\n- Implement permissive parsing (accept multiple input formats)\n- Provide strict canonical output","status":"open","priority":1,"issue_type":"epic","created_at":"2026-01-20T07:28:05.043998231-06:00","created_by":"damian","updated_at":"2026-01-20T07:28:19.871908925-06:00","dependencies":[{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-oiq","type":"blocks","created_at":"2026-01-20T07:29:48.169745493-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-a0z","type":"blocks","created_at":"2026-01-20T07:29:49.289955504-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-8f2","type":"blocks","created_at":"2026-01-20T07:29:51.318015724-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-9sd","type":"blocks","created_at":"2026-01-20T07:29:52.999294641-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-1cq","type":"blocks","created_at":"2026-01-20T07:29:54.517817556-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-vox","type":"blocks","created_at":"2026-01-20T07:29:55.498495366-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-zo1","type":"blocks","created_at":"2026-01-20T07:31:11.580941177-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-6am","type":"blocks","created_at":"2026-01-20T07:31:13.146924269-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-zd2","type":"blocks","created_at":"2026-01-20T07:31:14.34127596-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-7ps","type":"blocks","created_at":"2026-01-20T07:31:15.66909005-06:00","created_by":"damian"},{"issue_id":"morphir-python-3a9","depends_on_id":"morphir-python-rxn","type":"blocks","created_at":"2026-01-20T09:03:38.389836305-06:00","created_by":"damian"}]} +{"id":"morphir-python-6am","title":"Implement IR v4 Document Type","description":"# Implement IR v4 Document Type\n\nImplement the schema-less JSON-like data type for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/document.py`\n\n## Overview\n\nThe Document type provides a first-class, schema-less JSON-like data structure within the Morphir IR for representing untyped or dynamically-typed data.\n\n## Types to Implement\n\n### DocumentValue (recursive structure)\n- **DocNull**: JSON null\n- **DocBool**: JSON boolean\n- **DocInt**: JSON integer\n- **DocFloat**: JSON floating point\n- **DocString**: JSON string\n- **DocArray**: JSON array (ordered list)\n- **DocObject**: JSON object (string-keyed map)\n\n### Literal Extension\nAdd **DocumentLiteral** variant to the Literal type in values module.\n\n## Use Cases\n- External API responses where schema is unknown\n- Configuration settings\n- Pass-through opaque data\n- Metadata\n- JSON-based system interop\n\n## SDK Functions to Implement\n- Construction: `null()`, `bool()`, `int()`, `float()`, `string()`, `array()`, `object()`\n- Extraction: `as_bool()`, `as_int()`, `as_float()`, `as_string()`, `as_array()`, `as_object()`\n- Navigation: `get()`, `get_path()`\n- Predicates: `is_null()`, `is_bool()`, `is_int()`, `is_float()`, `is_string()`, `is_array()`, `is_object()`\n\n## JSON Serialization\n\n### Canonical Form\n```json\n{ \"DocObject\": {\n \"name\": { \"DocString\": \"Alice\" },\n \"age\": { \"DocInt\": 30 }\n }\n}\n```\n\n### Shorthand Form (for compact representation)\n```json\n{\n \"DocumentLiteral\": {\n \"name\": \"Alice\",\n \"age\": 30\n }\n}\n```\n\n### Decoding Rules\n- `null` → DocNull\n- `true/false` → DocBool\n- Integer number → DocInt\n- Floating number → DocFloat\n- String → DocString\n- Array → DocArray\n- Object → DocObject\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/document\n- finos/morphir repo: docs/design/draft/ir/document.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:31:10.212493884-06:00","created_by":"damian","updated_at":"2026-01-20T07:31:10.212493884-06:00"} +{"id":"morphir-python-7ps","title":"Implement IR v4 Decorations System","description":"# Implement IR v4 Decorations System\n\nImplement the layered metadata system for IR annotations in Morphir IR v4.\n\n## Location\n`packages/morphir/src/morphir/ir/decorations.py`\n\n## Overview\n\nDecorations attach additional metadata to IR nodes without modifying the core IR structure. They are stored separately in a layered, composable system.\n\n## Types to Implement\n\n### Schema Reference\n- **SchemaRef**: Reference to a decoration schema\n - `display_name: str`\n - `description: Option[str]`\n - `local_path: str`\n - `remote_ref: Option[str]`\n - `entry_point: FQName`\n - `cached_at: Option[str]`\n\n### Format Metadata\n- **DecorationFormat**: Top-level decoration system metadata\n - `format_version: str`\n - `schema_registry: Dict[str, SchemaRef]`\n - `layers: List[str]`\n - `layer_priority: Dict[str, int]`\n\n### Layer Manifest\n- **LayerManifest**: Metadata for a specific decoration layer\n - `format_version: str`\n - `layer: str`\n - `display_name: str`\n - `description: Option[str]`\n - `priority: int`\n - `decoration_types: List[str]`\n - `created_at: str`\n - `updated_at: str`\n\n### Decoration Values\n- **DecorationValuesFile**: Decoration values file\n - `format_version: str`\n - `decoration_type: str`\n - `layer: str`\n - `values: Dict[FQName, Any]` (validated against schema)\n\n### Decoration Targets\n- **DecorationTarget**: Node path for targeting\n - TypeTarget(fqname)\n - ValueTarget(fqname)\n - ModuleTarget(package, module)\n - PackageTarget(package)\n\n## Standard Layers\n- **core** (priority 0): Built-in from source\n- **tooling** (priority 50): Generated by tools\n- **user** (priority 100): User-defined\n\n## Merge Semantics\n- Primitive: Higher priority wins\n- Object: Deep merge recursively\n- Array: Concatenate (higher priority first)\n- Null: Higher priority wins (can \"unset\" lower layer)\n\n## Common Decoration Types\n- **Documentation**: summary, details, examples, params, returns, throws\n- **Deprecated**: since, replacement, reason, removalVersion, migrationGuide\n- **Tags**: List of string tags\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/decorations\n- finos/morphir repo: docs/design/draft/ir/decorations.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:31:12.714707371-06:00","created_by":"damian","updated_at":"2026-01-20T07:31:12.714707371-06:00"} +{"id":"morphir-python-8f2","title":"Implement IR v4 Packages Structure","description":"# Implement IR v4 Packages Structure\n\nImplement the package structure types for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/packages.py`\n\n## Types to Implement\n\n### Package Types\n- **PackageSpecification[A]**: Public interface for dependency resolution\n - `modules: Dict[ModulePath, ModuleSpecification[A]]`\n - Used when this package is a dependency of another\n\n- **PackageDefinition[A]**: Complete implementation\n - `modules: Dict[ModulePath, AccessControlled[ModuleDefinition[A]]]`\n - Used for the local project being compiled\n - Modules can be package-private\n\n## Package Hierarchy\n```\nPackageDefinition\n└── modules: Dict[ModulePath, AccessControlled[ModuleDefinition]]\n ā”œā”€ā”€ \"main/domain\" (Public)\n │ └── ModuleDefinition\n │ ā”œā”€ā”€ types: Dict[Name, AccessControlled[Documented[TypeDefinition]]]\n │ └── values: Dict[Name, AccessControlled[Documented[ValueDefinition]]]\n │\n └── \"internal/utils\" (Private)\n └── ModuleDefinition\n```\n\n## JSON Serialization\n\n### PackageSpecification\n```json\n{\n \"modules\": {\n \"main/domain\": {\n \"types\": { ... },\n \"values\": { ... }\n }\n }\n}\n```\n\n### PackageDefinition\n```json\n{\n \"modules\": {\n \"main/domain\": {\n \"access\": \"Public\",\n \"types\": { ... },\n \"values\": { ... }\n },\n \"internal/utils\": {\n \"access\": \"Private\",\n ...\n }\n }\n}\n```\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/packages\n- finos/morphir repo: docs/design/draft/ir/packages.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:42.431830834-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:42.431830834-06:00"} +{"id":"morphir-python-9sd","title":"Implement IR v4 Values Module","description":"# Implement IR v4 Values Module\n\nImplement the value expressions, literals, patterns, and definitions for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/values.py`\n\n## Types to Implement\n\n### Literals\n- **BoolLiteral**: Boolean (true, false)\n- **CharLiteral**: Single character\n- **StringLiteral**: Text string\n- **IntegerLiteral**: Integer (arbitrary precision, includes negatives)\n- **FloatLiteral**: Floating-point\n- **DecimalLiteral**: Arbitrary-precision decimal (stored as string)\n- **DocumentLiteral**: Schema-less JSON-like tree (v4 addition)\n\n### Patterns (for destructuring and matching)\n- **WildcardPattern**: Matches anything `_`\n- **AsPattern**: Binds a name while matching\n- **TuplePattern**: Matches tuple `(a, b, c)`\n- **ConstructorPattern**: Matches constructor (e.g., `Just x`)\n- **EmptyListPattern**: Matches `[]`\n- **HeadTailPattern**: Matches `x :: xs`\n- **LiteralPattern**: Matches literal value\n- **UnitPattern**: Matches `()`\n\n### Value Expressions (generic over attributes)\n- **Literal**: Literal constant\n- **Constructor**: Constructor reference\n- **Tuple**: Tuple value\n- **List**: List value\n- **Record**: Record value (field order doesn't affect equality)\n- **Unit**: Unit value\n- **Variable**: Variable reference\n- **Reference**: Reference to defined value\n- **Field**: Field access (record.fieldName)\n- **FieldFunction**: Field accessor function (.fieldName)\n- **Apply**: Function application (curried)\n- **Lambda**: Lambda expression\n- **LetDefinition**: Single let binding\n- **LetRecursion**: Mutually recursive let\n- **Destructure**: Pattern destructuring\n- **IfThenElse**: Conditional\n- **PatternMatch**: Pattern match (case expression)\n- **UpdateRecord**: Record update\n- **Hole**: Incomplete/broken reference (v4)\n- **Native**: Native platform operation (v4)\n- **External**: External FFI call (v4)\n\n### Value Definitions\n- **ValueDefinitionBody**: ExpressionBody, NativeBody, ExternalBody, IncompleteBody\n- **ValueDefinition**: Top-level value definition with access control\n- **ValueSpecification**: Public interface (signature only)\n\n### Supporting Types\n- **NativeInfo**: Information about native operations\n- **NativeHint**: Arithmetic, Comparison, StringOp, CollectionOp, PlatformSpecific\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/values\n- finos/morphir repo: docs/design/draft/ir/values.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:43.661953347-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:43.661953347-06:00"} +{"id":"morphir-python-a0z","title":"Implement IR v4 Naming Module","description":"# Implement IR v4 Naming Module\n\nImplement the naming types and utilities for the Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/naming.py`\n\n## Types to Implement\n\n### Core Types (as opaque wrappers for type safety)\n- **Name**: List of lowercase words, stored as canonical string (e.g., \"user-account\", \"value-in-(usd)\")\n- **Path**: Hierarchical namespace (list of Names), e.g., \"main/domain/orders\"\n- **TypeVariable**: Type variable name wrapper\n- **PackagePath**: Top-level namespace wrapper\n- **ModulePath**: Module path relative to package\n\n### Compound Types\n- **QName**: Module path + local name (e.g., \"main/domain#user-account\")\n- **FQName**: Package + Module + Local (e.g., \"morphir/sdk:list#map\")\n- **Uri**: Protocol-level URI with scheme (Pkg, Deps, Session)\n- **Locator**: Hybrid locator (ByIdentity or ByUri)\n\n### Error Types\n- **NameError**: EmptyName, EmptyWord, InvalidCharacter, WordMustBeLowercase\n- **PathError**: EmptyPath, InvalidSegment\n- **ParseError**: InvalidCanonicalName, InvalidCanonicalPath, etc.\n\n## Canonical String Format\n- Name: words joined by `-`, abbreviations in `()` → \"value-in-(usd)\"\n- Path: names joined by `/` → \"main/domain/orders\"\n- QName: {module-path}#{local} → \"main/domain#user-account\"\n- FQName: {package}:{module}#{local} → \"morphir/sdk:list#map\"\n\n## Abbreviation Handling\nConsecutive single-letter words are grouped in parentheses:\n- `[\"value\", \"in\", \"u\", \"s\", \"d\"]` → `\"value-in-(usd)\"`\n- `[\"my\", \"a\", \"p\", \"i\", \"client\"]` → `\"my-(api)-client\"`\n\n## Functions to Implement\n- Smart constructors: `name_from_words()`, `path_from_names()`, `name_from_string()`, etc.\n- Accessors: `name_to_string()`, `name_to_words()`, `path_to_string()`, etc.\n- Rendering: Support for camelCase, PascalCase, snake_case, kebab-case output\n- Permissive parsing: Accept multiple input formats, always output canonical\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/naming\n- finos/morphir repo: docs/design/draft/ir/naming.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:41.168878621-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:41.168878621-06:00"} +{"id":"morphir-python-c39","title":"Implement IR v4 Unit Tests","description":"# Implement IR v4 Unit Tests\n\nCreate comprehensive unit tests for all Morphir IR v4 types and serialization.\n\n## Location\n`tests/unit/ir/` directory\n\n## Test Coverage\n\n### Naming Tests (`test_naming.py`)\n- Name construction from words\n- Name parsing from various formats (canonical, camelCase, snake_case)\n- Abbreviation handling (grouping single letters)\n- Path construction and parsing\n- QName and FQName round-trip serialization\n- Error cases (empty names, invalid characters)\n\n### Types Tests (`test_types.py`)\n- Type expression construction\n- Type specification/definition variants\n- JSON serialization (both shorthand and canonical)\n- Backwards compatible decoding (v1/v2/v3 formats)\n- Record field ordering\n- Generic attribute handling\n\n### Values Tests (`test_values.py`)\n- Literal construction and serialization\n- Pattern construction and matching\n- Value expression variants\n- Value definition bodies\n- Lambda and Apply expressions\n- PatternMatch serialization\n\n### Modules Tests (`test_modules.py`)\n- Documentation construction and normalization\n- Documented wrapper serialization\n- ModuleSpecification and ModuleDefinition\n- Spec derivation from definition\n\n### Packages Tests (`test_packages.py`)\n- PackageSpecification serialization\n- PackageDefinition with access control\n- Package hierarchy traversal\n\n### Distributions Tests (`test_distributions.py`)\n- LibraryDistribution serialization\n- SpecsDistribution serialization\n- ApplicationDistribution with entry points\n- Semantic version parsing and comparison\n- VFS manifest formats\n\n### Decorations Tests (`test_decorations.py`)\n- Layer merge semantics\n- Decoration value file parsing\n- Schema reference handling\n\n### Document Tests (`test_document.py`)\n- DocumentValue construction\n- JSON round-trip serialization\n- Shorthand decoding\n\n### Meta/Refs Tests (`test_meta_refs.py`)\n- FileMeta parsing\n- $ref resolution\n- Circular reference detection\n\n## Test Approach\n- Use pytest fixtures for common test data\n- Property-based testing where appropriate (hypothesis)\n- Round-trip serialization tests\n- Edge case coverage","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T09:03:20.616955354-06:00","created_by":"damian","updated_at":"2026-01-20T09:03:20.616955354-06:00"} +{"id":"morphir-python-oiq","title":"Implement IR v4 Types Module","description":"# Implement IR v4 Types Module\n\nImplement the type system for the Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/types.py`\n\n## Types to Implement\n\n### Access Control\n- **Access**: Public | Private\n- **AccessControlled[A]**: Wraps any definition with visibility control\n\n### Type Expressions (generic over attributes)\n- **Variable**: Type variable reference (e.g., `a`, `comparable`)\n- **Reference**: Named type reference with args (e.g., `String`, `List Int`)\n- **Tuple**: Tuple type (e.g., `(Int, String)`)\n- **Record**: Record type with fields (e.g., `{ name: String, age: Int }`)\n- **ExtensibleRecord**: Extensible record (e.g., `{ a | name: String }`)\n- **Function**: Function type (e.g., `Int -\u003e String`)\n- **Unit**: Unit type `()`\n\n### Supporting Types\n- **Field[A]**: Record field (name + type)\n- **Constructor[A]**: Custom type constructor (name + args)\n\n### Type Specifications (public interface)\n- **TypeAliasSpecification**: Type alias visible to consumers\n- **OpaqueTypeSpecification**: Opaque type (no structure exposed)\n- **CustomTypeSpecification**: Custom type with public constructors\n- **DerivedTypeSpecification**: Opaque with conversion functions (serializable)\n\n### Type Definitions (implementation)\n- **CustomTypeDefinition**: Sum type implementation\n- **TypeAliasDefinition**: Type alias implementation\n- **IncompleteTypeDefinition**: Incomplete type (Hole or Draft) for v4 best-effort support\n\n### Incompleteness Types\n- **Incompleteness**: Hole | Draft\n- **HoleReason**: UnresolvedReference, DeletedDuringRefactor, TypeMismatch\n\n## JSON Serialization\n- Support both shorthand and canonical forms\n- Shorthand: `\"morphir/sdk:basics#int\"` for simple references\n- Shorthand: `[\"morphir/sdk:list#list\", \"morphir/sdk:basics#int\"]` for parameterized\n- Shorthand: `\"a\"` for type variables\n- Canonical: Full wrapper objects\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/types\n- finos/morphir repo: docs/design/draft/ir/types.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:39.932160508-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:39.932160508-06:00"} +{"id":"morphir-python-rxn","title":"Implement IR v4 VFS File I/O","description":"# Implement IR v4 VFS File I/O\n\nImplement VFS (Virtual File System) file reading and writing for the discrete distribution mode.\n\n## Location\n`packages/morphir/src/morphir/ir/vfs.py`\n\n## Overview\n\nSupport the VFS distribution mode where IR is stored as a directory tree with individual files per definition.\n\n## VFS Structure\n```\n.morphir-dist/\nā”œā”€ā”€ format.json # Distribution metadata\nā”œā”€ā”€ morphir.toml # Project configuration\nā”œā”€ā”€ session.jsonl # Transaction journal\nā”œā”€ā”€ pkg/ # Local project IR\n│ └── my-org/\n│ └── my-project/\n│ ā”œā”€ā”€ module.json\n│ ā”œā”€ā”€ types/\n│ │ └── user.type.json\n│ └── values/\n│ └── login.value.json\nā”œā”€ā”€ deps/ # Dependencies (versioned)\n│ └── morphir/\n│ └── sdk/\n│ └── 1.2.0/\n└── deco/ # Decorations\n ā”œā”€ā”€ format.json\n ā”œā”€ā”€ schemas/\n └── layers/\n```\n\n## Functions to Implement\n\n### Reading\n- `read_distribution(path)`: Read entire distribution from VFS or classic format\n- `read_format_manifest(path)`: Read format.json\n- `read_module_manifest(path)`: Read module.json\n- `read_type_file(path)`: Read *.type.json\n- `read_value_file(path)`: Read *.value.json\n- `read_decoration_layer(path)`: Read decoration layer\n\n### Writing\n- `write_distribution(path, dist)`: Write distribution to VFS\n- `write_format_manifest(path, manifest)`: Write format.json\n- `write_module_manifest(path, manifest)`: Write module.json\n- `write_type_file(path, type_def)`: Write *.type.json\n- `write_value_file(path, value_def)`: Write *.value.json\n\n### Utilities\n- `detect_distribution_mode(path)`: Detect classic vs VFS mode\n- `namespace_to_path(path)`: Convert IR path to filesystem path\n- `path_to_namespace(path)`: Convert filesystem path to IR path\n- `expand_refs_in_file(content)`: Expand $ref nodes\n\n## File Naming Conventions\n- Path segments: kebab-case directories (e.g., `main/domain/`)\n- Type files: `{name}.type.json`\n- Value files: `{name}.value.json`\n- Module manifest: `module.json`\n\n## Format Versioning\nAll files include `formatVersion: \"4.0.0\"` for schema compatibility.\n\n## Reference\n- VFS layout: finos/morphir docs/design/draft/ir/README.md\n- Distribution modes: finos/morphir docs/design/draft/ir/distributions.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T09:03:27.881348998-06:00","created_by":"damian","updated_at":"2026-01-20T09:03:27.881348998-06:00"} +{"id":"morphir-python-vox","title":"Implement IR v4 Modules Structure","description":"# Implement IR v4 Modules Structure\n\nImplement the module structure types for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/modules.py`\n\n## Types to Implement\n\n### Documentation\n- **Documentation**: Opaque type supporting single or multi-line content\n - Stored internally as normalized lines (no trailing \\r)\n - Handles both Unix (\\n) and Windows (\\r\\n) line endings\n - Functions: `doc_from_string()`, `doc_from_lines()`, `doc_to_string()`, `doc_to_lines()`, `doc_is_single_line()`\n\n### Documented Wrapper\n- **Documented[A]**: Generic documentation wrapper\n - `doc: Option[Documentation]`\n - `value: A`\n - Helper functions: `undocumented()`, `with_doc()`, `with_doc_lines()`\n\n### Module Types\n- **ModuleSpecification[A]**: Public interface exposed to consumers\n - `types: Dict[Name, Documented[TypeSpecification[A]]]`\n - `values: Dict[Name, Documented[ValueSpecification[A]]]`\n\n- **ModuleDefinition[A]**: Full implementation\n - `types: Dict[Name, AccessControlled[Documented[TypeDefinition[A]]]]`\n - `values: Dict[Name, AccessControlled[Documented[ValueDefinition[A]]]]`\n\n### Functions\n- `to_specification()`: Extract public specification from definition (filter to public items)\n- `to_type_spec()`: Convert TypeDefinition to TypeSpecification\n- `to_value_spec()`: Convert ValueDefinition to ValueSpecification\n\n## JSON Serialization\n\n### Flattening Rules\n- `Documented[A]` → `{ \"doc\": \"...\", ...a }` (doc inlined, omit if None)\n- `AccessControlled[A]` → `{ \"access\": \"Public\", ...a }`\n- Combined: `{ \"access\": \"Public\", \"doc\": \"...\", ...a }`\n\n### Documentation Serialization\n- String format: `\"Line 1\\nLine 2\"` (embedded newlines)\n- Array format: `[\"Line 1\", \"Line 2\"]` (explicit lines, preferred for multi-line)\n- Missing → None\n\n## Reference\n- Spec: https://morphir.finos.org/docs/design/draft/modules\n- finos/morphir repo: docs/design/draft/ir/modules.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:29:46.692010178-06:00","created_by":"damian","updated_at":"2026-01-20T07:29:46.692010178-06:00"} +{"id":"morphir-python-zd2","title":"Implement IR v4 JSON Serialization","description":"# Implement IR v4 JSON Serialization\n\nImplement JSON encoding and decoding for all Morphir IR v4 types in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/codec.py` (or per-module as appropriate)\n\n## Overview\n\nImplement bidirectional JSON serialization for all IR types with support for:\n- Canonical wrapper object format (primary output)\n- Shorthand formats (for readability, accepted on input)\n- Backwards compatible decoding (v1/v2/v3 formats)\n\n## Encoding Strategies\n\n### Type Expressions\n- Shorthand output when attributes are empty/null\n- `\"a\"` for type variables\n- `\"morphir/sdk:basics#int\"` for simple references\n- `[\"morphir/sdk:list#list\", ...]` for parameterized types\n\n### Disambiguation Logic (Decoding)\n- String with `:` and `#` → FQName reference\n- String without special chars → Variable name\n- Array → Parameterized type\n- Object → Canonical wrapper format\n\n### Wrapper Object Format\n```json\n{ \"Variable\": { \"name\": \"a\" } }\n{ \"Reference\": { \"fqname\": \"morphir/sdk:basics#int\", \"args\": [...] } }\n{ \"Record\": { \"fields\": { \"name\": ..., \"age\": ... } } }\n```\n\n## Flattening Rules\n\n### Documented and AccessControlled\n- `Documented[A]` → `{ \"doc\": \"...\", ...a }` (omit doc if None)\n- `AccessControlled[A]` → `{ \"access\": \"Public\", ...a }`\n- Combined: `{ \"access\": \"Public\", \"doc\": \"...\", ...a }`\n\n### Documentation Field\n- String format: `\"Line 1\\nLine 2\"` (split on newlines)\n- Array format: `[\"Line 1\", \"Line 2\"]` (explicit lines)\n- Encoding: Use array for multi-line, string for single-line\n\n## Backwards Compatible Decoding\n\nAccept multiple formats:\n- Wrapper object: `{ \"Variable\": { \"name\": \"a\" } }` (v4 canonical)\n- Tagged array (cap): `[\"Variable\", {}, [\"a\"]]` (v2/v3)\n- Tagged array (lower): `[\"variable\", {}, [\"a\"]]` (v1)\n\n## VFS File Formats\n\n### Type/Value Files\n```json\n{\n \"formatVersion\": \"4.0.0\",\n \"name\": \"user\",\n \"$meta\": { ... },\n \"$defs\": { ... },\n \"def\": { ... } // or \"spec\": { ... }\n}\n```\n\n### Module Manifest\n```json\n{\n \"formatVersion\": \"4.0.0\",\n \"path\": \"my-org/domain\",\n \"types\": [\"user\", \"order\"],\n \"values\": [\"create-user\"]\n}\n```\n\n### Distribution Format\n```json\n{\n \"formatVersion\": \"4.0.0\",\n \"distribution\": \"Library\",\n \"package\": \"my-org/project\",\n \"version\": \"1.0.0\"\n}\n```\n\n## Implementation Notes\n- Use Pydantic for automatic JSON serialization where possible\n- Implement custom encoders/decoders for shorthand support\n- Handle $ref expansion during decoding\n- Preserve unknown fields for forward compatibility\n\n## Reference\n- Type serialization: finos/morphir docs/design/draft/ir/types.md\n- Value serialization: finos/morphir docs/design/draft/ir/values.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:31:11.273743778-06:00","created_by":"damian","updated_at":"2026-01-20T07:31:11.273743778-06:00","dependencies":[{"issue_id":"morphir-python-zd2","depends_on_id":"morphir-python-c39","type":"blocks","created_at":"2026-01-20T09:03:38.285081426-06:00","created_by":"damian"},{"issue_id":"morphir-python-zd2","depends_on_id":"morphir-python-rxn","type":"blocks","created_at":"2026-01-20T09:03:38.537526874-06:00","created_by":"damian"}]} +{"id":"morphir-python-zo1","title":"Implement IR v4 Meta and Refs","description":"# Implement IR v4 Meta and Refs\n\nImplement file-level metadata ($meta) and node references ($ref) for Morphir IR v4 in Python.\n\n## Location\n`packages/morphir/src/morphir/ir/meta.py`\n`packages/morphir/src/morphir/ir/refs.py`\n\n## File Metadata ($meta)\n\n### SourceRange\n- `start: Tuple[int, int]` (line, column - 1-indexed)\n- `end: Tuple[int, int]` (line, column - 1-indexed)\n\n### FileMeta\n- Provenance: `source`, `source_range`, `compiler`, `generated`, `checksum`\n- Tooling: `edited_by`, `edited_at`, `locked`, `is_generated`\n- Extensions: `Dict[str, Any]` for tool-specific data\n\n### Functions\n- `parse_meta()`: Parse $meta from JSON\n- `merge_meta()`: Merge two FileMeta objects\n\n### Checksum Format\nAlgorithm-prefixed: `sha256:hexdigest`, `sha1:...`, `md5:...`\n\n## Node References ($ref)\n\n### Design\n- **File-local only**: References resolve within the same file\n- **JSON Schema style**: Uses `$defs` and `$ref` patterns\n- **Shorthand support**: Simple names resolve to `$defs`\n\n### Ref Types\n- **DefRef**: Shorthand reference to $defs entry\n- **PointerRef**: Full JSON Pointer reference\n\n### RefError Types\n- UnresolvedRef\n- InvalidPointer\n- CircularRef\n\n### Functions\n- `parse_ref()`: Parse a $ref string\n- `resolve_ref()`: Resolve within a file\n- `expand_refs()`: Expand all refs in a JSON value\n\n### Resolution Rules\n- `{ \"$ref\": \"user\" }` → `$defs.user`\n- `{ \"$ref\": \"#/$defs/user\" }` → Full JSON Pointer\n\n### Example with $defs\n```json\n{\n \"$defs\": {\n \"user\": { \"Reference\": { \"fqname\": \"my-org/domain:types#user\" } },\n \"maybe-user\": {\n \"Reference\": {\n \"fqname\": \"morphir/sdk:maybe#maybe\",\n \"args\": [{ \"$ref\": \"user\" }]\n }\n }\n },\n \"def\": {\n \"Record\": {\n \"fields\": {\n \"created-by\": { \"$ref\": \"user\" },\n \"updated-by\": { \"$ref\": \"user\" }\n }\n }\n }\n}\n```\n\n## Reference\n- Meta spec: finos/morphir repo docs/design/draft/ir/meta.md\n- Refs spec: finos/morphir repo docs/design/draft/ir/refs.md","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-20T07:31:08.423364293-06:00","created_by":"damian","updated_at":"2026-01-20T07:31:08.423364293-06:00"} diff --git a/.beads/metadata.json b/.beads/metadata.json new file mode 100644 index 00000000..c787975e --- /dev/null +++ b/.beads/metadata.json @@ -0,0 +1,4 @@ +{ + "database": "beads.db", + "jsonl_export": "issues.jsonl" +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..807d5983 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ + +# Use bd merge for beads JSONL files +.beads/issues.jsonl merge=beads diff --git a/AGENTS.md b/AGENTS.md index f041a321..b7b0e436 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -295,3 +295,29 @@ Result = Union[Ok[T], Err[E]] - All public APIs must have docstrings - Keep README.md up to date - Document non-obvious design decisions in code comments + +## Landing the Plane (Session Completion) + +**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. + +**MANDATORY WORKFLOW:** + +1. **File issues for remaining work** - Create issues for anything that needs follow-up +2. **Run quality gates** (if code changed) - Tests, linters, builds +3. **Update issue status** - Close finished work, update in-progress items +4. **PUSH TO REMOTE** - This is MANDATORY: + ```bash + git pull --rebase + bd sync + git push + git status # MUST show "up to date with origin" + ``` +5. **Clean up** - Clear stashes, prune remote branches +6. **Verify** - All changes committed AND pushed +7. **Hand off** - Provide context for next session + +**CRITICAL RULES:** +- Work is NOT complete until `git push` succeeds +- NEVER stop before pushing - that leaves work stranded locally +- NEVER say "ready to push when you are" - YOU must push +- If push fails, resolve and retry until it succeeds