dotdog 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +68 -0
- package/kits/dao/SPEC.dog +39 -0
- package/kits/dao/constitution.dog +9 -0
- package/kits/dao/data-model.dog +134 -0
- package/kits/saas/constitution.dog +8 -0
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -2895,6 +2895,21 @@ function parseBlocks(lines, start, end) {
|
|
|
2895
2895
|
}
|
|
2896
2896
|
}
|
|
2897
2897
|
}
|
|
2898
|
+
if (lines[i].startsWith("```")) {
|
|
2899
|
+
let fenceEnd = i + 1;
|
|
2900
|
+
while (fenceEnd < end && !lines[fenceEnd].startsWith("```"))
|
|
2901
|
+
fenceEnd++;
|
|
2902
|
+
const blockEnd = fenceEnd < end ? fenceEnd + 1 : end;
|
|
2903
|
+
blocks.push({
|
|
2904
|
+
kind: "prose",
|
|
2905
|
+
content: lines.slice(i, blockEnd).join(`
|
|
2906
|
+
`).trim(),
|
|
2907
|
+
lineStart: i + 1,
|
|
2908
|
+
lineEnd: blockEnd
|
|
2909
|
+
});
|
|
2910
|
+
i = blockEnd;
|
|
2911
|
+
continue;
|
|
2912
|
+
}
|
|
2898
2913
|
const proseStart = i;
|
|
2899
2914
|
while (i < end && !isBlockStart(lines[i]) && !lines[i].startsWith("```")) {
|
|
2900
2915
|
i++;
|
|
@@ -4660,6 +4675,59 @@ kitCmd.command("init <kit>").description("Init a project from a kit").option("-p
|
|
|
4660
4675
|
Kit "${kit}" initialized in specs/${projectName}/`));
|
|
4661
4676
|
console.log(source_default.gray(` Run: dotdog validate`));
|
|
4662
4677
|
});
|
|
4678
|
+
program2.command("badge [dir]").description("Generate dotdog-badge.svg (shields.io style) showing savings").action((d = ".") => {
|
|
4679
|
+
const dir = resolvePath2(d);
|
|
4680
|
+
const dirs = [join3(dir, "projects"), join3(dir, "specs"), dir];
|
|
4681
|
+
let found = false;
|
|
4682
|
+
for (const dd of dirs) {
|
|
4683
|
+
if (!existsSync3(dd))
|
|
4684
|
+
continue;
|
|
4685
|
+
const projects = readdirSync3(dd, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
4686
|
+
for (const p of projects) {
|
|
4687
|
+
const pd = join3(dd, p);
|
|
4688
|
+
const dagFile = join3(pd, `${p}.dag`);
|
|
4689
|
+
if (!existsSync3(join3(pd, "SPEC.dog")))
|
|
4690
|
+
continue;
|
|
4691
|
+
if (!existsSync3(dagFile)) {
|
|
4692
|
+
console.log(source_default.red(` No .dag for ${p}. Run dotdog compile first.`));
|
|
4693
|
+
continue;
|
|
4694
|
+
}
|
|
4695
|
+
const dag = JSON.parse(readFileSync3(dagFile, "utf-8"));
|
|
4696
|
+
const savings = dag.tk && dag.tk.sv ? Math.round(dag.tk.sv) : 0;
|
|
4697
|
+
const label = "spec savings";
|
|
4698
|
+
const value = `${savings}%`;
|
|
4699
|
+
const color = savings > 90 ? "#4c1" : savings > 70 ? "#dfb317" : "#e05d44";
|
|
4700
|
+
const labelLen = Math.round(label.length * 7.2);
|
|
4701
|
+
const valueLen = Math.round(value.length * 7.2);
|
|
4702
|
+
const leftW = Math.max(labelLen + 10, 70);
|
|
4703
|
+
const rightW = Math.max(valueLen + 10, 40);
|
|
4704
|
+
const totalW = leftW + rightW;
|
|
4705
|
+
const leftX = leftW / 2 * 10;
|
|
4706
|
+
const rightX = (leftW + rightW / 2) * 10;
|
|
4707
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${totalW}" height="20" role="img" aria-label="${label}: ${value}">
|
|
4708
|
+
<title>${label}: ${value}</title>
|
|
4709
|
+
<linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient>
|
|
4710
|
+
<clipPath id="r"><rect width="${totalW}" height="20" rx="3" fill="#fff"/></clipPath>
|
|
4711
|
+
<g clip-path="url(#r)">
|
|
4712
|
+
<rect width="${leftW}" height="20" fill="#555"/>
|
|
4713
|
+
<rect x="${leftW}" width="${rightW}" height="20" fill="${color}"/>
|
|
4714
|
+
<rect width="${totalW}" height="20" fill="url(#s)"/>
|
|
4715
|
+
</g>
|
|
4716
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
|
|
4717
|
+
<g transform="scale(.1)">
|
|
4718
|
+
<text x="${leftX}" y="140" textLength="${labelLen * 10}">${label}</text>
|
|
4719
|
+
<text x="${rightX}" y="140" textLength="${valueLen * 10}">${value}</text>
|
|
4720
|
+
</g>
|
|
4721
|
+
</g>
|
|
4722
|
+
</svg>`;
|
|
4723
|
+
writeFileSync2(join3(dir, "dotdog-badge.svg"), svg);
|
|
4724
|
+
console.log(source_default.green(` ✓ dotdog-badge.svg (${label}: ${value})`));
|
|
4725
|
+
found = true;
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
if (!found)
|
|
4729
|
+
console.log(source_default.yellow("No projects found. Run dotdog init first."));
|
|
4730
|
+
});
|
|
4663
4731
|
program2.parse();
|
|
4664
4732
|
export {
|
|
4665
4733
|
parseToJSON,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# DAO Governance
|
|
2
|
+
|
|
3
|
+
> Community governance starter. Members create proposals, vote, and execute approved treasury actions.
|
|
4
|
+
|
|
5
|
+
## Product
|
|
6
|
+
|
|
7
|
+
A DAO governance workspace. Members join with voting power, submit proposals, cast votes, and execute passed proposals against a shared treasury.
|
|
8
|
+
|
|
9
|
+
## What the User Sees
|
|
10
|
+
|
|
11
|
+
### Screen: Proposal List
|
|
12
|
+
|
|
13
|
+
+------------------------------------------+
|
|
14
|
+
| DAO Proposals [New] |
|
|
15
|
+
|------------------------------------------|
|
|
16
|
+
| Upgrade Grants Program Active |
|
|
17
|
+
| Fund Security Audit Passed |
|
|
18
|
+
| Sponsor Builder Event Draft |
|
|
19
|
+
+------------------------------------------+
|
|
20
|
+
|
|
21
|
+
### Screen: Proposal Detail
|
|
22
|
+
|
|
23
|
+
+------------------------------------------+
|
|
24
|
+
| Upgrade Grants Program |
|
|
25
|
+
|------------------------------------------|
|
|
26
|
+
| Status: Active |
|
|
27
|
+
| For: 62% Against: 18% Abstain: 20% |
|
|
28
|
+
| |
|
|
29
|
+
| [Vote For] [Vote Against] [Abstain] |
|
|
30
|
+
+------------------------------------------+
|
|
31
|
+
|
|
32
|
+
## User Stories
|
|
33
|
+
|
|
34
|
+
| ID | Story | Pri | Acceptance |
|
|
35
|
+
|----|-------|-----|------------|
|
|
36
|
+
| US-01 | Member creates a proposal | P0 | Proposal appears as draft |
|
|
37
|
+
| US-02 | Member casts a vote | P0 | Vote is counted once |
|
|
38
|
+
| US-03 | Proposal reaches quorum | P0 | Status becomes passed or rejected |
|
|
39
|
+
| US-04 | Approved proposal executes | P1 | Treasury allocation is recorded |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# DAO Governance Constitution
|
|
2
|
+
|
|
3
|
+
## Core Rules
|
|
4
|
+
|
|
5
|
+
1. One member can cast one vote per proposal.
|
|
6
|
+
2. Proposal execution requires both quorum and majority approval.
|
|
7
|
+
3. Treasury allocations must reference an approved proposal.
|
|
8
|
+
4. Proposal state changes are append-only and auditable.
|
|
9
|
+
5. Voting power is read at the proposal snapshot block.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# DAO Governance Data Model
|
|
2
|
+
|
|
3
|
+
## Entities
|
|
4
|
+
|
|
5
|
+
### Entity: Member
|
|
6
|
+
|
|
7
|
+
A DAO participant with voting power.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
entity: Member
|
|
11
|
+
type: entity
|
|
12
|
+
properties:
|
|
13
|
+
id:
|
|
14
|
+
type: string
|
|
15
|
+
required: true
|
|
16
|
+
wallet:
|
|
17
|
+
type: string
|
|
18
|
+
required: true
|
|
19
|
+
voting_power:
|
|
20
|
+
type: number
|
|
21
|
+
required: true
|
|
22
|
+
states: [active, delegated, suspended]
|
|
23
|
+
lifecycle: active → delegated → suspended
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Entity: Proposal
|
|
27
|
+
|
|
28
|
+
A governance item submitted for member voting.
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
entity: Proposal
|
|
32
|
+
type: entity
|
|
33
|
+
properties:
|
|
34
|
+
id:
|
|
35
|
+
type: string
|
|
36
|
+
required: true
|
|
37
|
+
title:
|
|
38
|
+
type: string
|
|
39
|
+
required: true
|
|
40
|
+
quorum_required:
|
|
41
|
+
type: number
|
|
42
|
+
required: true
|
|
43
|
+
status:
|
|
44
|
+
type: enum
|
|
45
|
+
required: true
|
|
46
|
+
states: [draft, active, passed, rejected, executed]
|
|
47
|
+
lifecycle: draft → active → passed → executed
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Entity: Vote
|
|
51
|
+
|
|
52
|
+
A member decision on a proposal.
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
entity: Vote
|
|
56
|
+
type: event
|
|
57
|
+
properties:
|
|
58
|
+
member_id:
|
|
59
|
+
type: string
|
|
60
|
+
required: true
|
|
61
|
+
proposal_id:
|
|
62
|
+
type: string
|
|
63
|
+
required: true
|
|
64
|
+
choice:
|
|
65
|
+
type: enum
|
|
66
|
+
required: true
|
|
67
|
+
weight:
|
|
68
|
+
type: number
|
|
69
|
+
required: true
|
|
70
|
+
states: [cast, counted]
|
|
71
|
+
lifecycle: cast → counted
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Entity: TreasuryAllocation
|
|
75
|
+
|
|
76
|
+
Funds allocated by an executed proposal.
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
entity: TreasuryAllocation
|
|
80
|
+
type: entity
|
|
81
|
+
properties:
|
|
82
|
+
id:
|
|
83
|
+
type: string
|
|
84
|
+
required: true
|
|
85
|
+
proposal_id:
|
|
86
|
+
type: string
|
|
87
|
+
required: true
|
|
88
|
+
amount:
|
|
89
|
+
type: number
|
|
90
|
+
required: true
|
|
91
|
+
recipient:
|
|
92
|
+
type: string
|
|
93
|
+
required: true
|
|
94
|
+
states: [approved, executed, canceled]
|
|
95
|
+
lifecycle: approved → executed
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Relationships
|
|
99
|
+
|
|
100
|
+
### Relationship: Member → Proposal
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
relationship: Member → Proposal
|
|
104
|
+
verb: submits
|
|
105
|
+
cardinality: 1:N
|
|
106
|
+
required: true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Relationship: Member → Vote
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
relationship: Member → Vote
|
|
113
|
+
verb: casts
|
|
114
|
+
cardinality: 1:N
|
|
115
|
+
required: true
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Relationship: Proposal → Vote
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
relationship: Proposal → Vote
|
|
122
|
+
verb: receives
|
|
123
|
+
cardinality: 1:N
|
|
124
|
+
required: true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Relationship: Proposal → TreasuryAllocation
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
relationship: Proposal → TreasuryAllocation
|
|
131
|
+
verb: authorizes
|
|
132
|
+
cardinality: 1:1
|
|
133
|
+
required: false
|
|
134
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# SaaS Platform Constitution
|
|
2
|
+
|
|
3
|
+
## Core Rules
|
|
4
|
+
|
|
5
|
+
1. Organizations own their workspace data.
|
|
6
|
+
2. Users access data only through organization membership.
|
|
7
|
+
3. Plan limits must be enforced before billable usage is accepted.
|
|
8
|
+
4. Subscription state controls access to paid features.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotdog",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "CLI tool for structured software specifications. Validate .dog files, compile .dag graphs, query via MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -47,5 +47,8 @@
|
|
|
47
47
|
"homepage": "https://specdog.github.io/dotdog",
|
|
48
48
|
"bugs": {
|
|
49
49
|
"url": "https://github.com/specdog/dotdog/issues"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"lint": "bun run --check src/"
|
|
50
53
|
}
|
|
51
54
|
}
|