Skip to content

Commit cdc3559

Browse files
committed
chorse: Improve quality of repo
1 parent 75114dc commit cdc3559

File tree

119 files changed

+9505
-400
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+9505
-400
lines changed

.gitattributes

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
3+
4+
# Go source files
5+
*.go text eol=lf
6+
7+
# Bash scripts
8+
*.sh text eol=lf
9+
10+
# Markdown and documentation
11+
*.md text eol=lf
12+
13+
# JSON and data files
14+
*.json text eol=lf
15+
*.xml text eol=lf
16+
*.toml text eol=lf
17+
*.yaml text eol=lf
18+
*.yml text eol=lf
19+
20+
# Lock files (generated, but treat as text)
21+
*.lock text eol=lf linguist-generated=true
22+
23+
# Binary files
24+
*.png binary
25+
*.jpg binary
26+
*.jpeg binary
27+
*.gif binary
28+
*.ico binary
29+
*.svg binary
30+
*.pdf binary
31+
*.woff binary
32+
*.woff2 binary
33+
34+
# SVG files - mark as generated/binary to avoid noisy diffs in examples
35+
*.svg linguist-generated=true
36+
37+
# Output and coverage files - mark as generated
38+
*.out linguist-generated=true
39+
coverage*.out linguist-generated=true
40+
41+
# Example outputs - mark as generated
42+
/output/** linguist-generated=true
43+
/examples/real/*.json linguist-generated=true
44+
/examples/test/*.json linguist-generated=true
45+
46+
# Cache files
47+
/blogpost/cache/** linguist-generated=true
48+
49+
# Archive files
50+
*.zip binary
51+
*.tar binary
52+
*.gz binary
53+
*.tgz binary
54+
*.bz2 binary
55+
56+
# Go binaries
57+
/bin/* binary
58+
59+
# Treat go.sum as generated (don't show in diffs by default on GitHub)
60+
go.sum linguist-generated=true
61+

.github/CODEOWNERS

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# CODEOWNERS
2+
#
3+
# This file defines individuals or teams responsible for code in this repository.
4+
# Code owners are automatically requested for review when someone opens a pull request
5+
# that modifies code that they own.
6+
#
7+
# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
8+
9+
# Default owner for everything in the repo
10+
* @matzehuels
11+
12+
# Core packages
13+
/pkg/ @matzehuels
14+
/internal/ @matzehuels
15+
16+
# CI/CD and infrastructure
17+
/.github/ @matzehuels
18+
/Makefile @matzehuels
19+
20+
# Documentation
21+
/README.md @matzehuels
22+
/CONTRIBUTING.md @matzehuels
23+
/CODE_OF_CONDUCT.md @matzehuels
24+
/SECURITY.md @matzehuels
25+
/blogpost/ @matzehuels
26+
27+
# Dependencies
28+
/go.mod @matzehuels
29+
/go.sum @matzehuels
30+

CODE_OF_CONDUCT.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
We as members, contributors, and leaders pledge to make participation in our
6+
community a harassment-free experience for everyone, regardless of age, body
7+
size, visible or invisible disability, ethnicity, sex characteristics, gender
8+
identity and expression, level of experience, education, socio-economic status,
9+
nationality, personal appearance, race, caste, color, religion, or sexual
10+
identity and orientation.
11+
12+
We pledge to act and interact in ways that contribute to an open, welcoming,
13+
diverse, inclusive, and healthy community.
14+
15+
## Our Standards
16+
17+
Examples of behavior that contributes to a positive environment for our
18+
community include:
19+
20+
* Demonstrating empathy and kindness toward other people
21+
* Being respectful of differing opinions, viewpoints, and experiences
22+
* Giving and gracefully accepting constructive feedback
23+
* Accepting responsibility and apologizing to those affected by our mistakes,
24+
and learning from the experience
25+
* Focusing on what is best not just for us as individuals, but for the overall
26+
community
27+
28+
Examples of unacceptable behavior include:
29+
30+
* The use of sexualized language or imagery, and sexual attention or advances of
31+
any kind
32+
* Trolling, insulting or derogatory comments, and personal or political attacks
33+
* Public or private harassment
34+
* Publishing others' private information, such as a physical or email address,
35+
without their explicit permission
36+
* Other conduct which could reasonably be considered inappropriate in a
37+
professional setting
38+
39+
## Enforcement Responsibilities
40+
41+
Community leaders are responsible for clarifying and enforcing our standards of
42+
acceptable behavior and will take appropriate and fair corrective action in
43+
response to any behavior that they deem inappropriate, threatening, offensive,
44+
or harmful.
45+
46+
Community leaders have the right and responsibility to remove, edit, or reject
47+
comments, commits, code, wiki edits, issues, and other contributions that are
48+
not aligned to this Code of Conduct, and will communicate reasons for moderation
49+
decisions when appropriate.
50+
51+
## Scope
52+
53+
This Code of Conduct applies within all community spaces, and also applies when
54+
an individual is officially representing the community in public spaces.
55+
Examples of representing our community include using an official e-mail address,
56+
posting via an official social media account, or acting as an appointed
57+
representative at an online or offline event.
58+
59+
## Enforcement
60+
61+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
62+
reported to the community leaders responsible for enforcement via:
63+
64+
- GitHub Issues (for non-sensitive matters)
65+
- Direct contact with the maintainer (see GitHub profile)
66+
67+
All complaints will be reviewed and investigated promptly and fairly.
68+
69+
All community leaders are obligated to respect the privacy and security of the
70+
reporter of any incident.
71+
72+
## Enforcement Guidelines
73+
74+
Community leaders will follow these Community Impact Guidelines in determining
75+
the consequences for any action they deem in violation of this Code of Conduct:
76+
77+
### 1. Correction
78+
79+
**Community Impact**: Use of inappropriate language or other behavior deemed
80+
unprofessional or unwelcome in the community.
81+
82+
**Consequence**: A private, written warning from community leaders, providing
83+
clarity around the nature of the violation and an explanation of why the
84+
behavior was inappropriate. A public apology may be requested.
85+
86+
### 2. Warning
87+
88+
**Community Impact**: A violation through a single incident or series of
89+
actions.
90+
91+
**Consequence**: A warning with consequences for continued behavior. No
92+
interaction with the people involved, including unsolicited interaction with
93+
those enforcing the Code of Conduct, for a specified period of time. This
94+
includes avoiding interactions in community spaces as well as external channels
95+
like social media. Violating these terms may lead to a temporary or permanent
96+
ban.
97+
98+
### 3. Temporary Ban
99+
100+
**Community Impact**: A serious violation of community standards, including
101+
sustained inappropriate behavior.
102+
103+
**Consequence**: A temporary ban from any sort of interaction or public
104+
communication with the community for a specified period of time. No public or
105+
private interaction with the people involved, including unsolicited interaction
106+
with those enforcing the Code of Conduct, is allowed during this period.
107+
Violating these terms may lead to a permanent ban.
108+
109+
### 4. Permanent Ban
110+
111+
**Community Impact**: Demonstrating a pattern of violation of community
112+
standards, including sustained inappropriate behavior, harassment of an
113+
individual, or aggression toward or disparagement of classes of individuals.
114+
115+
**Consequence**: A permanent ban from any sort of public interaction within the
116+
community.
117+
118+
## Attribution
119+
120+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
121+
version 2.1, available at
122+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
123+
124+
Community Impact Guidelines were inspired by
125+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
126+
127+
For answers to common questions about this code of conduct, see the FAQ at
128+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
129+
[https://www.contributor-covenant.org/translations][translations].
130+
131+
[homepage]: https://www.contributor-covenant.org
132+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
133+
[Mozilla CoC]: https://github.com/mozilla/diversity
134+
[FAQ]: https://www.contributor-covenant.org/faq
135+
[translations]: https://www.contributor-covenant.org/translations
136+

CONTRIBUTING.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,116 @@ make e2e # End-to-end tests
4040
make cover # Tests with coverage
4141
```
4242

43+
## Architecture
44+
45+
Stacktower follows a clean layered architecture. See the [pkg.go.dev documentation](https://pkg.go.dev/github.com/matzehuels/stacktower) for detailed API docs.
46+
47+
```
48+
internal/cli/ # Command-line interface
49+
pkg/dag/ # Core DAG data structure
50+
├── transform/ # Graph normalization (transitive reduction, subdivision)
51+
└── perm/ # PQ-tree and permutation algorithms
52+
pkg/deps/ # Dependency resolution from registries
53+
├── python/ # Python: PyPI + poetry.lock + requirements.txt
54+
├── rust/ # Rust: crates.io + Cargo.toml
55+
├── javascript/ # JavaScript: npm + package.json
56+
├── ruby/ # Ruby: RubyGems + Gemfile
57+
├── php/ # PHP: Packagist + composer.json
58+
├── java/ # Java: Maven Central + pom.xml
59+
├── golang/ # Go: Go Module Proxy + go.mod
60+
└── metadata/ # GitHub/GitLab enrichment providers
61+
pkg/integrations/ # Registry API clients (npm, pypi, crates, etc.)
62+
pkg/render/tower/ # Tower visualization
63+
├── ordering/ # Barycentric and optimal ordering algorithms
64+
├── layout/ # Block position computation
65+
├── sink/ # Output formats (SVG, JSON, PDF, PNG)
66+
└── styles/ # Visual styles (handdrawn, simple)
67+
pkg/io/ # JSON import/export
68+
```
69+
70+
## Adding a New Language
71+
72+
1. **Create an integration client** in `pkg/integrations/<registry>/client.go`:
73+
74+
```go
75+
type Client struct {
76+
*integrations.Client
77+
baseURL string
78+
}
79+
80+
func NewClient(cacheTTL time.Duration) (*Client, error) {
81+
cache, err := integrations.NewCache(cacheTTL)
82+
if err != nil {
83+
return nil, err
84+
}
85+
return &Client{
86+
Client: integrations.NewClient(cache, nil),
87+
baseURL: "https://registry.example.com",
88+
}, nil
89+
}
90+
91+
func (c *Client) FetchPackage(ctx context.Context, name string, refresh bool) (*PackageInfo, error) {
92+
// Implement caching and fetching
93+
}
94+
```
95+
96+
2. **Create a language definition** in `pkg/deps/<lang>/<lang>.go`:
97+
98+
```go
99+
var Language = &deps.Language{
100+
Name: "mylang",
101+
DefaultRegistry: "myregistry",
102+
RegistryAliases: map[string]string{"alias": "myregistry"},
103+
ManifestTypes: []string{"my.lock"},
104+
ManifestAliases: map[string]string{"my.lock": "mylock"},
105+
NewResolver: newResolver,
106+
NewManifest: newManifest,
107+
ManifestParsers: manifestParsers,
108+
}
109+
```
110+
111+
3. **Register in CLI** in `internal/cli/parse.go`
112+
113+
See [`pkg/deps`](https://pkg.go.dev/github.com/matzehuels/stacktower/pkg/deps) for detailed documentation.
114+
115+
## Adding a Manifest Parser
116+
117+
Implement the `ManifestParser` interface:
118+
119+
```go
120+
type MyLockParser struct{}
121+
122+
func (p *MyLockParser) Type() string { return "my.lock" }
123+
func (p *MyLockParser) IncludesTransitive() bool { return true }
124+
func (p *MyLockParser) Supports(name string) bool { return name == "my.lock" }
125+
126+
func (p *MyLockParser) Parse(path string, opts deps.Options) (*deps.ManifestResult, error) {
127+
g := dag.New(nil)
128+
// ... populate nodes and edges
129+
return &deps.ManifestResult{Graph: g, Type: p.Type(), IncludesTransitive: true}, nil
130+
}
131+
```
132+
133+
## Adding a New Output Format
134+
135+
Output formats are "sinks" in `pkg/render/tower/sink/`. Each sink takes a `layout.Layout` and renders it to bytes.
136+
137+
1. **Create a sink file** in `pkg/render/tower/sink/<format>.go`:
138+
139+
```go
140+
func RenderMyFormat(l layout.Layout, opts ...MyFormatOption) ([]byte, error) {
141+
// Access layout data:
142+
// - l.FrameWidth, l.FrameHeight: canvas dimensions
143+
// - l.Blocks: map[string]Block with position data
144+
// - l.RowOrders: node ordering per row
145+
return []byte("..."), nil
146+
}
147+
```
148+
149+
2. **Register in CLI** in `internal/cli/render.go`
150+
151+
See [`pkg/render/tower/sink`](https://pkg.go.dev/github.com/matzehuels/stacktower/pkg/render/tower/sink) for existing implementations.
152+
43153
## Questions?
44154

45155
Open an [issue](https://github.com/matzehuels/stacktower/issues) — we're happy to help!

0 commit comments

Comments
 (0)