Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions .cursor/commands/supermemory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
---
description: Initialize Supermemory with comprehensive codebase knowledge
---

# Initializing Supermemory

You are initializing persistent memory for this codebase. This is not just data collection - you're building context that will make you significantly more effective across all future sessions.

## Understanding Context

You are a **stateful** coding agent. Users expect to work with you over extended periods - potentially the entire lifecycle of a project. Your memory is how you get better over time and maintain continuity.

## What to Remember

### 1. Procedures (Rules & Workflows)
Explicit rules that should always be followed:
- "Never commit directly to main - always use feature branches"
- "Always run lint before tests"
- "Use conventional commits format"

### 2. Preferences (Style & Conventions)
Project and user coding style:
- "Prefer functional components over class components"
- "Use early returns instead of nested conditionals"
- "Always add JSDoc to exported functions"

### 3. Architecture & Context
How the codebase works and why:
- "Auth system was refactored in v2.0 - old patterns deprecated"
- "The monorepo used to have 3 modules before consolidation"
- "This pagination bug was fixed before - similar to PR #234"

## Memory Scopes

**Project-scoped** (`scope: "project"`):
- Build/test/lint commands
- Architecture and key directories
- Team conventions specific to this codebase
- Technology stack and framework choices
- Known issues and their solutions

**User-scoped** (`scope: "user"`):
- Personal coding preferences across all projects
- Communication style preferences
- General workflow habits

## Research Approach

This is a **deep research** initialization. Take your time and be thorough (~50+ tool calls). The goal is to genuinely understand the project, not just collect surface-level facts.

**What to uncover:**
- Tech stack and dependencies (explicit and implicit)
- Project structure and architecture
- Build/test/deploy commands and workflows
- Contributors & team dynamics (who works on what?)
- Commit conventions and branching strategy
- Code evolution (major refactors, architecture changes)
- Pain points (areas with lots of bug fixes)
- Implicit conventions not documented anywhere

## Research Techniques

### File-based
- README.md, CONTRIBUTING.md, AGENTS.md, CLAUDE.md
- Package manifests (package.json, Cargo.toml, pyproject.toml, go.mod, Gemfile)
- Config files (.eslintrc, tsconfig.json, .prettierrc)
- CI/CD configs (.github/workflows/)

### Git-based
- `git log --oneline -20` - Recent history
- `git branch -a` - Branching strategy
- `git log --format="%s" -50` - Commit conventions
- `git shortlog -sn --all | head -10` - Main contributors

### Explore Agent
Fire parallel explore queries for broad understanding:
```
Task(explore, "What is the tech stack and key dependencies?")
Task(explore, "What is the project structure? Key directories?")
Task(explore, "How do you build, test, and run this project?")
Task(explore, "What are the main architectural patterns?")
Task(explore, "What conventions or patterns are used?")
```

## How to Do Thorough Research

**Don't just collect data - analyze and cross-reference.**

Bad (shallow):
- Run commands, copy output
- List facts without understanding

Good (thorough):
- Cross-reference findings (if inconsistent, dig deeper)
- Resolve ambiguities (don't leave questions unanswered)
- Read actual file content, not just names
- Look for patterns (what do commits tell you about workflow?)
- Think like a new team member - what would you want to know?

## Saving Memories

Use the `supermemory` tool for each distinct insight:

```
supermemory(mode: "add", content: "...", type: "...", scope: "project")
```

**Types:**
- `project-config` - tech stack, commands, tooling
- `architecture` - codebase structure, key components, data flow
- `learned-pattern` - conventions specific to this codebase
- `error-solution` - known issues and their fixes
- `preference` - coding style preferences (use with user scope)

**Guidelines:**
- Save each distinct insight as a separate memory
- Be concise but include enough context to be useful
- Include the "why" not just the "what" when relevant
- Update memories incrementally as you research (don't wait until the end)

**Good memories:**
- "Uses Bun runtime and package manager. Commands: bun install, bun run dev, bun test"
- "API routes in src/routes/, handlers in src/handlers/. Hono framework."
- "Auth uses Redis sessions, not JWT. Implementation in src/lib/auth.ts"
- "Never use `any` type - strict TypeScript. Use `unknown` and narrow."
- "Database migrations must be backward compatible - we do rolling deploys"

## Upfront Questions

Before diving in, ask:
1. "Any specific rules I should always follow?"
2. "Preferences for how I communicate? (terse/detailed)"

## Reflection Phase

Before finishing, reflect:
1. **Completeness**: Did you cover commands, architecture, conventions, gotchas?
2. **Quality**: Are memories concise and searchable?
3. **Scope**: Did you correctly separate project vs user knowledge?

Then ask: "I've initialized memory with X insights. Want me to continue refining, or is this good?"

## Your Task

1. Ask upfront questions (research depth, rules, preferences)
2. Check existing memories: `supermemory(mode: "list", scope: "project")`
3. Research based on chosen depth
4. Save memories incrementally as you discover insights
5. Reflect and verify completeness
6. Summarize what was learned and ask if user wants refinement
2 changes: 2 additions & 0 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,5 @@ jobs:
- name: Run ruff
run: uvx ruff check json2xml tests

- name: Run type check
run: uvx ty check json2xml
61 changes: 27 additions & 34 deletions json2xml/dicttoxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from decimal import Decimal
from fractions import Fraction
from random import SystemRandom
from typing import Any, Union, cast
from typing import Any, cast

from defusedxml.minidom import parseString

Expand Down Expand Up @@ -43,33 +43,24 @@ def get_unique_id(element: str) -> str:
Returns:
str: The unique ID.
"""
ids: list[str] = [] # initialize list of unique ids
this_id = make_id(element)
dup = True
while dup:
if this_id not in ids:
dup = False
ids.append(this_id)
else:
this_id = make_id(element)
return ids[-1]


ELEMENT = Union[
str,
int,
float,
bool,
complex,
Decimal,
Fraction,
numbers.Number,
Sequence[Any],
datetime.datetime,
datetime.date,
None,
dict[str, Any],
]
return make_id(element)


ELEMENT = (
str
| int
| float
| bool
| complex
| Decimal
| Fraction
| numbers.Number
| Sequence[Any]
| datetime.datetime
| datetime.date
| None
| dict[str, Any]
)


def get_xml_type(val: ELEMENT) -> str:
Expand Down Expand Up @@ -332,15 +323,14 @@ def dict2xml_str(
cdata: bool,
item_name: str,
item_wrap: bool,
parentIsList: bool,
parent_is_list: bool,
parent: str = "",
list_headers: bool = False,
) -> str:
"""
parse dict2xml
"""
ids: list[str] = [] # initialize list of unique ids
", ".join(str(key) for key in item)
subtree = "" # Initialize subtree with default empty string

if attr_type:
Expand All @@ -358,12 +348,12 @@ def dict2xml_str(
rawitem, ids, attr_type, item_func, cdata, item_wrap, item_name, list_headers=list_headers
)

if parentIsList and list_headers:
if parent_is_list and list_headers:
if len(val_attr) > 0 and not item_wrap:
attrstring = make_attrstring(val_attr)
return f"<{parent}{attrstring}>{subtree}</{parent}>"
return f"<{parent}>{subtree}</{parent}>"
elif item.get("@flat", False) or (parentIsList and not item_wrap):
elif item.get("@flat", False) or (parent_is_list and not item_wrap):
return subtree

attrstring = make_attrstring(val_attr)
Expand Down Expand Up @@ -553,7 +543,7 @@ def convert_list(
cdata=cdata,
item_name=item_name,
item_wrap=item_wrap,
parentIsList=True,
parent_is_list=True,
parent=parent,
list_headers=list_headers
)
Expand Down Expand Up @@ -640,7 +630,7 @@ def dicttoxml(
item_wrap: bool = True,
item_func: Callable[[str], str] = default_item_func,
cdata: bool = False,
xml_namespaces: dict[str, Any] = {},
xml_namespaces: dict[str, Any] | None = None,
list_headers: bool = False,
xpath_format: bool = False,
) -> bytes:
Expand Down Expand Up @@ -794,6 +784,9 @@ def dicttoxml(
]
return "".join(output).encode("utf-8")

if xml_namespaces is None:
xml_namespaces = {}

output = []
namespace_str = ""
for prefix in xml_namespaces:
Expand Down
7 changes: 6 additions & 1 deletion json2xml/json2xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ def __init__(
self.item_wrap = item_wrap
self.xpath_format = xpath_format

def to_xml(self) -> Any | None:
def to_xml(self) -> str | bytes | None:
"""
Convert to xml using dicttoxml.dicttoxml and then pretty print it.

Returns:
str: Pretty-printed XML string when pretty=True.
bytes: Raw XML bytes when pretty=False.
None: When data is empty or None.
"""
if self.data:
xml_data = dicttoxml.dicttoxml(
Expand Down
11 changes: 6 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ dependencies = [
"defusedxml",
"urllib3",
"xmltodict>=0.12.0",
"pytest",
"pytest-cov",
"coverage",
"setuptools",
]

[project.urls]
Expand All @@ -44,8 +40,13 @@ Homepage = "https://github.com/vinitkumar/json2xml"
include = ["json2xml"]

[project.optional-dependencies]
test = [
dev = [
"pytest>=8.4.1",
"pytest-cov",
"pytest-xdist",
"coverage",
"ruff",
"setuptools",
]

[tool.pytest.ini_options]
Expand Down
Loading
Loading