@medicine-wheel/community-review 0.2.2
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/README.md +117 -0
- package/dist/accountability.d.ts +52 -0
- package/dist/accountability.d.ts.map +1 -0
- package/dist/accountability.js +140 -0
- package/dist/accountability.js.map +1 -0
- package/dist/circle.d.ts +38 -0
- package/dist/circle.d.ts.map +1 -0
- package/dist/circle.js +86 -0
- package/dist/circle.js.map +1 -0
- package/dist/consensus.d.ts +43 -0
- package/dist/consensus.d.ts.map +1 -0
- package/dist/consensus.js +128 -0
- package/dist/consensus.js.map +1 -0
- package/dist/elder.d.ts +30 -0
- package/dist/elder.d.ts.map +1 -0
- package/dist/elder.js +77 -0
- package/dist/elder.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/outcomes.d.ts +27 -0
- package/dist/outcomes.d.ts.map +1 -0
- package/dist/outcomes.js +76 -0
- package/dist/outcomes.js.map +1 -0
- package/dist/schemas.d.ts +371 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +69 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @medicine-wheel/community-review
|
|
2
|
+
|
|
3
|
+
> Community-based ceremonial review protocol — implements Wilson's validation through Elder review circles, consensus-seeking, and relational accountability assessment.
|
|
4
|
+
|
|
5
|
+
Part of the [Medicine Wheel Developer Suite](https://github.com/jgwill/medicine-wheel).
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Wilson describes research validation not through peer review but through *community review* — Elders, knowledge keepers, and community members validate whether research honors relational accountability. This package implements that vision.
|
|
10
|
+
|
|
11
|
+
## Core Concepts
|
|
12
|
+
|
|
13
|
+
### Review Circle
|
|
14
|
+
A community body that evaluates an artifact through talking circle, Elder validation, and consensus. Circles progress through: `gathering → reviewing → deliberating → decided`.
|
|
15
|
+
|
|
16
|
+
### Talking Circle
|
|
17
|
+
Each participant shares their voice in turn, honoring all directions. Voices are recorded with directional and role context.
|
|
18
|
+
|
|
19
|
+
### Elder Validation
|
|
20
|
+
Elders provide final validation and blessing, ensuring artifacts honor relational accountability.
|
|
21
|
+
|
|
22
|
+
### Wilson's Three R's Check
|
|
23
|
+
Every review outcome includes a check against Wilson's three R's:
|
|
24
|
+
- **Respect** — Are all perspectives honored?
|
|
25
|
+
- **Reciprocity** — Does the artifact give back?
|
|
26
|
+
- **Responsibility** — Is accountability explicit?
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import {
|
|
32
|
+
createReviewCircle,
|
|
33
|
+
addReviewer,
|
|
34
|
+
submitForReview,
|
|
35
|
+
talkingCircle,
|
|
36
|
+
requestElderValidation,
|
|
37
|
+
seekConsensus,
|
|
38
|
+
approveWithBlessings,
|
|
39
|
+
closeCircle,
|
|
40
|
+
} from '@medicine-wheel/community-review';
|
|
41
|
+
|
|
42
|
+
// Create a circle
|
|
43
|
+
let circle = createReviewCircle('research-001', 'research');
|
|
44
|
+
|
|
45
|
+
// Add reviewers
|
|
46
|
+
circle = addReviewer(circle, {
|
|
47
|
+
id: 'reviewer-1',
|
|
48
|
+
role: 'steward',
|
|
49
|
+
direction: 'east',
|
|
50
|
+
accountableTo: ['community', 'future-generations'],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Submit for review
|
|
54
|
+
circle = submitForReview(circle);
|
|
55
|
+
|
|
56
|
+
// Add voices in the talking circle
|
|
57
|
+
circle = talkingCircle(circle, {
|
|
58
|
+
speakerId: 'reviewer-1',
|
|
59
|
+
role: 'steward',
|
|
60
|
+
direction: 'east',
|
|
61
|
+
voice: 'This research honors the land and our relations.',
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Request Elder validation
|
|
66
|
+
circle = requestElderValidation(circle, 'elder-1');
|
|
67
|
+
|
|
68
|
+
// Seek consensus
|
|
69
|
+
const consensus = seekConsensus(circle);
|
|
70
|
+
|
|
71
|
+
// Produce outcome
|
|
72
|
+
const outcome = approveWithBlessings(circle, 'This work carries our blessing.');
|
|
73
|
+
circle = closeCircle(circle, outcome);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API
|
|
77
|
+
|
|
78
|
+
### Circle Management
|
|
79
|
+
- `createReviewCircle(artifactId, artifactType)` — Create a new circle
|
|
80
|
+
- `addReviewer(circle, reviewer)` — Add a participant
|
|
81
|
+
- `submitForReview(circle)` — Transition to reviewing
|
|
82
|
+
- `closeCircle(circle, outcome)` — Finalize with outcome
|
|
83
|
+
- `circleStatus(circle)` — Current state summary
|
|
84
|
+
|
|
85
|
+
### Elder Validation
|
|
86
|
+
- `requestElderValidation(circle, elderId)` — Request Elder review
|
|
87
|
+
- `elderGuidance(circle)` — Get Elder's guidance
|
|
88
|
+
- `elderBlessing(circle, elderId, blessing)` — Record blessing
|
|
89
|
+
|
|
90
|
+
### Consensus
|
|
91
|
+
- `seekConsensus(circle)` — Attempt consensus
|
|
92
|
+
- `talkingCircle(circle, entry)` — Add a talking circle entry
|
|
93
|
+
- `recordVoices(circle)` — Summarize all voices
|
|
94
|
+
- `resolveDisagreement(circle, process)` — Handle disagreement
|
|
95
|
+
|
|
96
|
+
### Accountability
|
|
97
|
+
- `reviewerAccountability(reviewer)` — Accountability chain
|
|
98
|
+
- `reviewAgainstWilson(circle)` — Check against Wilson's 3 R's
|
|
99
|
+
- `reviewAgainstOcap(circle)` — Check against OCAP®
|
|
100
|
+
- `relationalHealthReview(circle)` — Assess relational health
|
|
101
|
+
|
|
102
|
+
### Outcomes
|
|
103
|
+
- `approveWithBlessings(circle, blessing)` — Approve
|
|
104
|
+
- `requestDeepening(circle, areas)` — Needs more work
|
|
105
|
+
- `returnToCircle(circle, reason)` — Send back
|
|
106
|
+
- `ceremonialHold(circle, reason)` — Pause for ceremony
|
|
107
|
+
|
|
108
|
+
## Dependencies
|
|
109
|
+
|
|
110
|
+
- `@medicine-wheel/ontology-core` ^0.1.1
|
|
111
|
+
- `@medicine-wheel/ceremony-protocol` ^0.1.0
|
|
112
|
+
- `zod` ^3.23.0
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
|
117
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/community-review — Accountability
|
|
3
|
+
*
|
|
4
|
+
* Review functions that assess artifacts against Wilson's three R's,
|
|
5
|
+
* OCAP® principles, and relational health.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReviewCircle, Reviewer, WilsonCheck } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Determine who a reviewer is accountable to.
|
|
10
|
+
* Returns the accountability chain for a given reviewer.
|
|
11
|
+
*/
|
|
12
|
+
export declare function reviewerAccountability(reviewer: Reviewer): {
|
|
13
|
+
reviewerId: string;
|
|
14
|
+
role: string;
|
|
15
|
+
accountableTo: string[];
|
|
16
|
+
direction?: string;
|
|
17
|
+
accountabilityStatement: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Check an artifact (via its review circle) against Wilson's three R's:
|
|
21
|
+
* Respect, Reciprocity, Responsibility.
|
|
22
|
+
*/
|
|
23
|
+
export declare function reviewAgainstWilson(circle: ReviewCircle): {
|
|
24
|
+
wilsonCheck: WilsonCheck;
|
|
25
|
+
score: number;
|
|
26
|
+
observations: string[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Check an artifact's review against OCAP® principles:
|
|
30
|
+
* Ownership, Control, Access, Possession.
|
|
31
|
+
*/
|
|
32
|
+
export declare function reviewAgainstOcap(circle: ReviewCircle): {
|
|
33
|
+
compliant: boolean;
|
|
34
|
+
issues: string[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Assess the relational health of the review circle itself.
|
|
38
|
+
* A healthy circle has diverse perspectives, active participation,
|
|
39
|
+
* and explicit accountability.
|
|
40
|
+
*/
|
|
41
|
+
export declare function relationalHealthReview(circle: ReviewCircle): {
|
|
42
|
+
healthy: boolean;
|
|
43
|
+
score: number;
|
|
44
|
+
dimensions: {
|
|
45
|
+
diversity: number;
|
|
46
|
+
participation: number;
|
|
47
|
+
accountability: number;
|
|
48
|
+
elderPresence: number;
|
|
49
|
+
};
|
|
50
|
+
recommendations: string[];
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=accountability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountability.d.ts","sourceRoot":"","sources":["../src/accountability.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAiBA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG;IACzD,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CA+CA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG;IACvD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CA0BA;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CA6CA"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/community-review — Accountability
|
|
4
|
+
*
|
|
5
|
+
* Review functions that assess artifacts against Wilson's three R's,
|
|
6
|
+
* OCAP® principles, and relational health.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.reviewerAccountability = reviewerAccountability;
|
|
10
|
+
exports.reviewAgainstWilson = reviewAgainstWilson;
|
|
11
|
+
exports.reviewAgainstOcap = reviewAgainstOcap;
|
|
12
|
+
exports.relationalHealthReview = relationalHealthReview;
|
|
13
|
+
/**
|
|
14
|
+
* Determine who a reviewer is accountable to.
|
|
15
|
+
* Returns the accountability chain for a given reviewer.
|
|
16
|
+
*/
|
|
17
|
+
function reviewerAccountability(reviewer) {
|
|
18
|
+
const roleStatements = {
|
|
19
|
+
steward: 'As steward, accountable to the community and future generations for the care of this knowledge.',
|
|
20
|
+
contributor: 'As contributor, accountable to the circle for the integrity of contributions.',
|
|
21
|
+
elder: 'As elder, accountable to the ancestors and the community for wise guidance.',
|
|
22
|
+
firekeeper: 'As firekeeper, accountable to the ceremony and all participants for maintaining sacred space.',
|
|
23
|
+
'community-member': 'As community member, accountable to the community for honest voice.',
|
|
24
|
+
youth: 'As youth, accountable to future generations for carrying the teachings forward.',
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
reviewerId: reviewer.id,
|
|
28
|
+
role: reviewer.role,
|
|
29
|
+
accountableTo: reviewer.accountableTo,
|
|
30
|
+
direction: reviewer.direction,
|
|
31
|
+
accountabilityStatement: roleStatements[reviewer.role] ?? 'Accountable to all relations.',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check an artifact (via its review circle) against Wilson's three R's:
|
|
36
|
+
* Respect, Reciprocity, Responsibility.
|
|
37
|
+
*/
|
|
38
|
+
function reviewAgainstWilson(circle) {
|
|
39
|
+
const observations = [];
|
|
40
|
+
// Respect: Are all directions and roles represented?
|
|
41
|
+
const directions = new Set(circle.reviewers.filter((r) => r.direction).map((r) => r.direction));
|
|
42
|
+
const respectHonored = directions.size >= 2 && circle.reviewers.length >= 2;
|
|
43
|
+
if (!respectHonored) {
|
|
44
|
+
observations.push('Respect: Not all perspectives are represented in the circle');
|
|
45
|
+
}
|
|
46
|
+
// Reciprocity: Has the artifact given back to the community?
|
|
47
|
+
const hasElderVoice = circle.talkingCircleLog.some((e) => e.role === 'elder');
|
|
48
|
+
const hasCommunityVoice = circle.talkingCircleLog.some((e) => e.role === 'community-member' || e.role === 'youth');
|
|
49
|
+
const reciprocityPresent = hasElderVoice || hasCommunityVoice;
|
|
50
|
+
if (!reciprocityPresent) {
|
|
51
|
+
observations.push('Reciprocity: Elder or community voices have not been heard');
|
|
52
|
+
}
|
|
53
|
+
// Responsibility: Has accountability been explicitly stated?
|
|
54
|
+
const reviewersWithAccountability = circle.reviewers.filter((r) => r.accountableTo.length > 0);
|
|
55
|
+
const responsibilityTaken = reviewersWithAccountability.length === circle.reviewers.length &&
|
|
56
|
+
circle.reviewers.length > 0;
|
|
57
|
+
if (!responsibilityTaken) {
|
|
58
|
+
observations.push('Responsibility: Not all reviewers have stated their accountability');
|
|
59
|
+
}
|
|
60
|
+
const wilsonCheck = {
|
|
61
|
+
respectHonored,
|
|
62
|
+
reciprocityPresent,
|
|
63
|
+
responsibilityTaken,
|
|
64
|
+
};
|
|
65
|
+
const trueCount = [respectHonored, reciprocityPresent, responsibilityTaken].filter(Boolean).length;
|
|
66
|
+
const score = trueCount / 3;
|
|
67
|
+
if (observations.length === 0) {
|
|
68
|
+
observations.push("Wilson's three R's are honored in this review circle");
|
|
69
|
+
}
|
|
70
|
+
return { wilsonCheck, score, observations };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check an artifact's review against OCAP® principles:
|
|
74
|
+
* Ownership, Control, Access, Possession.
|
|
75
|
+
*/
|
|
76
|
+
function reviewAgainstOcap(circle) {
|
|
77
|
+
const issues = [];
|
|
78
|
+
// Check that community ownership is represented
|
|
79
|
+
const hasSteward = circle.reviewers.some((r) => r.role === 'steward');
|
|
80
|
+
if (!hasSteward) {
|
|
81
|
+
issues.push('Ownership: No steward present to represent community ownership');
|
|
82
|
+
}
|
|
83
|
+
// Check that review process includes community control
|
|
84
|
+
const hasElderOrFirekeeper = circle.reviewers.some((r) => r.role === 'elder' || r.role === 'firekeeper');
|
|
85
|
+
if (!hasElderOrFirekeeper) {
|
|
86
|
+
issues.push('Control: No elder or firekeeper to ensure community control');
|
|
87
|
+
}
|
|
88
|
+
// Check that access considerations are addressed
|
|
89
|
+
if (!circle.ocapCompliant) {
|
|
90
|
+
issues.push('Access/Possession: OCAP® compliance has not been confirmed');
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
compliant: issues.length === 0,
|
|
94
|
+
issues,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Assess the relational health of the review circle itself.
|
|
99
|
+
* A healthy circle has diverse perspectives, active participation,
|
|
100
|
+
* and explicit accountability.
|
|
101
|
+
*/
|
|
102
|
+
function relationalHealthReview(circle) {
|
|
103
|
+
const recommendations = [];
|
|
104
|
+
// Diversity: How many directions and roles are represented?
|
|
105
|
+
const uniqueDirections = new Set(circle.reviewers.filter((r) => r.direction).map((r) => r.direction)).size;
|
|
106
|
+
const uniqueRoles = new Set(circle.reviewers.map((r) => r.role)).size;
|
|
107
|
+
const diversity = Math.min(1, (uniqueDirections + uniqueRoles) / 8);
|
|
108
|
+
if (diversity < 0.5) {
|
|
109
|
+
recommendations.push('Invite reviewers from underrepresented directions and roles');
|
|
110
|
+
}
|
|
111
|
+
// Participation: What fraction of reviewers have spoken?
|
|
112
|
+
const spoke = new Set(circle.talkingCircleLog.map((e) => e.speakerId));
|
|
113
|
+
const participation = circle.reviewers.length > 0
|
|
114
|
+
? [...new Set(circle.reviewers.map((r) => r.id))].filter((id) => spoke.has(id)).length / circle.reviewers.length
|
|
115
|
+
: 0;
|
|
116
|
+
if (participation < 0.75) {
|
|
117
|
+
recommendations.push('Not all reviewers have been heard — invite remaining voices');
|
|
118
|
+
}
|
|
119
|
+
// Accountability: Do all reviewers have stated accountability?
|
|
120
|
+
const withAccountability = circle.reviewers.filter((r) => r.accountableTo.length > 0).length;
|
|
121
|
+
const accountability = circle.reviewers.length > 0
|
|
122
|
+
? withAccountability / circle.reviewers.length
|
|
123
|
+
: 0;
|
|
124
|
+
if (accountability < 1) {
|
|
125
|
+
recommendations.push('Some reviewers have not stated who they are accountable to');
|
|
126
|
+
}
|
|
127
|
+
// Elder presence
|
|
128
|
+
const elderPresence = circle.elderValidator ? 1 : 0;
|
|
129
|
+
if (!elderPresence) {
|
|
130
|
+
recommendations.push('Consider requesting Elder validation');
|
|
131
|
+
}
|
|
132
|
+
const score = (diversity + participation + accountability + elderPresence) / 4;
|
|
133
|
+
return {
|
|
134
|
+
healthy: score >= 0.6,
|
|
135
|
+
score,
|
|
136
|
+
dimensions: { diversity, participation, accountability, elderPresence },
|
|
137
|
+
recommendations,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=accountability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountability.js","sourceRoot":"","sources":["../src/accountability.ts"],"names":[],"mappings":"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"}
|
package/dist/circle.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/community-review — Circle Management
|
|
3
|
+
*
|
|
4
|
+
* Creates and manages review circles — the community body
|
|
5
|
+
* that evaluates artifacts through ceremonial review.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReviewCircle, ReviewCircleStatus, Reviewer, ReviewOutcome, ArtifactType } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create a new review circle for an artifact.
|
|
10
|
+
* Initializes in 'gathering' status, awaiting reviewers.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createReviewCircle(artifactId: string, artifactType: ArtifactType): ReviewCircle;
|
|
13
|
+
/**
|
|
14
|
+
* Add a reviewer to the circle.
|
|
15
|
+
* Only allowed while status is 'gathering'.
|
|
16
|
+
*/
|
|
17
|
+
export declare function addReviewer(circle: ReviewCircle, reviewer: Reviewer): ReviewCircle;
|
|
18
|
+
/**
|
|
19
|
+
* Transition the circle to 'reviewing' status.
|
|
20
|
+
* Requires at least one reviewer.
|
|
21
|
+
*/
|
|
22
|
+
export declare function submitForReview(circle: ReviewCircle): ReviewCircle;
|
|
23
|
+
/**
|
|
24
|
+
* Close the circle with a final outcome.
|
|
25
|
+
* Transitions status to 'decided'.
|
|
26
|
+
*/
|
|
27
|
+
export declare function closeCircle(circle: ReviewCircle, outcome: ReviewOutcome): ReviewCircle;
|
|
28
|
+
/**
|
|
29
|
+
* Get a summary of the circle's current state.
|
|
30
|
+
*/
|
|
31
|
+
export declare function circleStatus(circle: ReviewCircle): {
|
|
32
|
+
status: ReviewCircleStatus;
|
|
33
|
+
reviewerCount: number;
|
|
34
|
+
hasElder: boolean;
|
|
35
|
+
voicesHeard: number;
|
|
36
|
+
outcomeType?: string;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=circle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../src/circle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,YAAY,GACzB,YAAY,CAYd;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,QAAQ,GACjB,YAAY,CAUd;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAalE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAa,GACrB,YAAY,CAWd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG;IAClD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAQA"}
|
package/dist/circle.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/community-review — Circle Management
|
|
4
|
+
*
|
|
5
|
+
* Creates and manages review circles — the community body
|
|
6
|
+
* that evaluates artifacts through ceremonial review.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createReviewCircle = createReviewCircle;
|
|
10
|
+
exports.addReviewer = addReviewer;
|
|
11
|
+
exports.submitForReview = submitForReview;
|
|
12
|
+
exports.closeCircle = closeCircle;
|
|
13
|
+
exports.circleStatus = circleStatus;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new review circle for an artifact.
|
|
16
|
+
* Initializes in 'gathering' status, awaiting reviewers.
|
|
17
|
+
*/
|
|
18
|
+
function createReviewCircle(artifactId, artifactType) {
|
|
19
|
+
return {
|
|
20
|
+
id: `circle-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
21
|
+
artifactId,
|
|
22
|
+
artifactType,
|
|
23
|
+
reviewers: [],
|
|
24
|
+
status: 'gathering',
|
|
25
|
+
talkingCircleLog: [],
|
|
26
|
+
wilsonAlignment: 0,
|
|
27
|
+
ocapCompliant: false,
|
|
28
|
+
createdAt: new Date().toISOString(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Add a reviewer to the circle.
|
|
33
|
+
* Only allowed while status is 'gathering'.
|
|
34
|
+
*/
|
|
35
|
+
function addReviewer(circle, reviewer) {
|
|
36
|
+
if (circle.status !== 'gathering') {
|
|
37
|
+
throw new Error(`Cannot add reviewer — circle is '${circle.status}', must be 'gathering'`);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
...circle,
|
|
41
|
+
reviewers: [...circle.reviewers, reviewer],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Transition the circle to 'reviewing' status.
|
|
46
|
+
* Requires at least one reviewer.
|
|
47
|
+
*/
|
|
48
|
+
function submitForReview(circle) {
|
|
49
|
+
if (circle.status !== 'gathering') {
|
|
50
|
+
throw new Error(`Cannot submit — circle is '${circle.status}', must be 'gathering'`);
|
|
51
|
+
}
|
|
52
|
+
if (circle.reviewers.length === 0) {
|
|
53
|
+
throw new Error('Cannot submit — circle has no reviewers');
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
...circle,
|
|
57
|
+
status: 'reviewing',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Close the circle with a final outcome.
|
|
62
|
+
* Transitions status to 'decided'.
|
|
63
|
+
*/
|
|
64
|
+
function closeCircle(circle, outcome) {
|
|
65
|
+
if (circle.status !== 'deliberating' && circle.status !== 'reviewing') {
|
|
66
|
+
throw new Error(`Cannot close — circle is '${circle.status}', must be 'reviewing' or 'deliberating'`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...circle,
|
|
70
|
+
status: 'decided',
|
|
71
|
+
outcome,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get a summary of the circle's current state.
|
|
76
|
+
*/
|
|
77
|
+
function circleStatus(circle) {
|
|
78
|
+
return {
|
|
79
|
+
status: circle.status,
|
|
80
|
+
reviewerCount: circle.reviewers.length,
|
|
81
|
+
hasElder: circle.elderValidator !== undefined,
|
|
82
|
+
voicesHeard: circle.talkingCircleLog.length,
|
|
83
|
+
outcomeType: circle.outcome?.type,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=circle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circle.js","sourceRoot":"","sources":["../src/circle.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAcH,gDAeC;AAMD,kCAaC;AAMD,0CAaC;AAMD,kCAcC;AAKD,oCAcC;AAhGD;;;GAGG;AACH,SAAgB,kBAAkB,CAChC,UAAkB,EAClB,YAA0B;IAE1B,OAAO;QACL,EAAE,EAAE,UAAU,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QACpE,UAAU;QACV,YAAY;QACZ,SAAS,EAAE,EAAE;QACb,MAAM,EAAE,WAAW;QACnB,gBAAgB,EAAE,EAAE;QACpB,eAAe,EAAE,CAAC;QAClB,aAAa,EAAE,KAAK;QACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CACzB,MAAoB,EACpB,QAAkB;IAElB,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,oCAAoC,MAAM,CAAC,MAAM,wBAAwB,CAC1E,CAAC;IACJ,CAAC;IACD,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EAAE,CAAC,GAAG,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,MAAoB;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,8BAA8B,MAAM,CAAC,MAAM,wBAAwB,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,GAAG,MAAM;QACT,MAAM,EAAE,WAAW;KACpB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CACzB,MAAoB,EACpB,OAAsB;IAEtB,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CACb,6BAA6B,MAAM,CAAC,MAAM,0CAA0C,CACrF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,GAAG,MAAM;QACT,MAAM,EAAE,SAAS;QACjB,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,MAAoB;IAO/C,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,aAAa,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;QACtC,QAAQ,EAAE,MAAM,CAAC,cAAc,KAAK,SAAS;QAC7C,WAAW,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM;QAC3C,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/community-review — Consensus & Talking Circle
|
|
3
|
+
*
|
|
4
|
+
* Manages the talking circle process and consensus-seeking.
|
|
5
|
+
* In Wilson's framework, validation comes through community
|
|
6
|
+
* consensus, not individual expert judgment.
|
|
7
|
+
*/
|
|
8
|
+
import type { ReviewCircle, TalkingCircleEntry, ReviewOutcomeType } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Attempt to reach consensus by analyzing all voices in the circle.
|
|
11
|
+
* Returns whether consensus exists and the emerging outcome type.
|
|
12
|
+
*/
|
|
13
|
+
export declare function seekConsensus(circle: ReviewCircle): {
|
|
14
|
+
consensusReached: boolean;
|
|
15
|
+
emergingOutcome: ReviewOutcomeType | null;
|
|
16
|
+
voiceCount: number;
|
|
17
|
+
reviewerCount: number;
|
|
18
|
+
allReviewersSpoken: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Add a talking circle entry — one person's voice in the circle.
|
|
22
|
+
* Validates the speaker is a participant.
|
|
23
|
+
*/
|
|
24
|
+
export declare function talkingCircle(circle: ReviewCircle, entry: TalkingCircleEntry): ReviewCircle;
|
|
25
|
+
/**
|
|
26
|
+
* Summarize all voices heard in the circle, grouped by direction.
|
|
27
|
+
*/
|
|
28
|
+
export declare function recordVoices(circle: ReviewCircle): {
|
|
29
|
+
total: number;
|
|
30
|
+
byDirection: Record<string, TalkingCircleEntry[]>;
|
|
31
|
+
byRole: Record<string, TalkingCircleEntry[]>;
|
|
32
|
+
unheardReviewers: string[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Process for handling disagreement within the circle.
|
|
36
|
+
* Returns guidance for resolution based on the process type.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveDisagreement(circle: ReviewCircle, process: 'deeper-listening' | 'elder-mediation' | 'return-to-ceremony' | 'rest-and-return'): {
|
|
39
|
+
guidance: string;
|
|
40
|
+
nextStatus: 'reviewing' | 'deliberating';
|
|
41
|
+
suggestedActions: string[];
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=consensus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consensus.d.ts","sourceRoot":"","sources":["../src/consensus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG;IACnD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CA4BA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,kBAAkB,GACxB,YAAY,CAWd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC7C,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAwBA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,iBAAiB,GACzF;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,WAAW,GAAG,cAAc,CAAC;IACzC,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CA2CA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/community-review — Consensus & Talking Circle
|
|
4
|
+
*
|
|
5
|
+
* Manages the talking circle process and consensus-seeking.
|
|
6
|
+
* In Wilson's framework, validation comes through community
|
|
7
|
+
* consensus, not individual expert judgment.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.seekConsensus = seekConsensus;
|
|
11
|
+
exports.talkingCircle = talkingCircle;
|
|
12
|
+
exports.recordVoices = recordVoices;
|
|
13
|
+
exports.resolveDisagreement = resolveDisagreement;
|
|
14
|
+
/**
|
|
15
|
+
* Attempt to reach consensus by analyzing all voices in the circle.
|
|
16
|
+
* Returns whether consensus exists and the emerging outcome type.
|
|
17
|
+
*/
|
|
18
|
+
function seekConsensus(circle) {
|
|
19
|
+
const reviewerIds = new Set(circle.reviewers.map((r) => r.id));
|
|
20
|
+
const spokePeople = new Set(circle.talkingCircleLog.map((e) => e.speakerId));
|
|
21
|
+
const allSpoken = [...reviewerIds].every((id) => spokePeople.has(id));
|
|
22
|
+
// Consensus requires all reviewers to have spoken
|
|
23
|
+
const consensusReached = allSpoken && circle.reviewers.length > 0;
|
|
24
|
+
// Determine emerging outcome based on whether voices align
|
|
25
|
+
let emergingOutcome = null;
|
|
26
|
+
if (consensusReached && circle.elderValidator) {
|
|
27
|
+
const elderSpoke = circle.talkingCircleLog.some((e) => e.speakerId === circle.elderValidator && e.role === 'elder');
|
|
28
|
+
emergingOutcome = elderSpoke ? 'approved-with-blessings' : 'deepen-required';
|
|
29
|
+
}
|
|
30
|
+
else if (consensusReached) {
|
|
31
|
+
emergingOutcome = 'deepen-required';
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
consensusReached,
|
|
35
|
+
emergingOutcome,
|
|
36
|
+
voiceCount: circle.talkingCircleLog.length,
|
|
37
|
+
reviewerCount: circle.reviewers.length,
|
|
38
|
+
allReviewersSpoken: allSpoken,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Add a talking circle entry — one person's voice in the circle.
|
|
43
|
+
* Validates the speaker is a participant.
|
|
44
|
+
*/
|
|
45
|
+
function talkingCircle(circle, entry) {
|
|
46
|
+
if (circle.status !== 'reviewing' && circle.status !== 'deliberating') {
|
|
47
|
+
throw new Error(`Cannot add to talking circle — circle is '${circle.status}'`);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
...circle,
|
|
51
|
+
talkingCircleLog: [...circle.talkingCircleLog, entry],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Summarize all voices heard in the circle, grouped by direction.
|
|
56
|
+
*/
|
|
57
|
+
function recordVoices(circle) {
|
|
58
|
+
const byDirection = {};
|
|
59
|
+
const byRole = {};
|
|
60
|
+
for (const entry of circle.talkingCircleLog) {
|
|
61
|
+
const dir = entry.direction ?? 'unaligned';
|
|
62
|
+
if (!byDirection[dir])
|
|
63
|
+
byDirection[dir] = [];
|
|
64
|
+
byDirection[dir].push(entry);
|
|
65
|
+
if (!byRole[entry.role])
|
|
66
|
+
byRole[entry.role] = [];
|
|
67
|
+
byRole[entry.role].push(entry);
|
|
68
|
+
}
|
|
69
|
+
const spoke = new Set(circle.talkingCircleLog.map((e) => e.speakerId));
|
|
70
|
+
const unheardReviewers = circle.reviewers
|
|
71
|
+
.filter((r) => !spoke.has(r.id))
|
|
72
|
+
.map((r) => r.id);
|
|
73
|
+
return {
|
|
74
|
+
total: circle.talkingCircleLog.length,
|
|
75
|
+
byDirection,
|
|
76
|
+
byRole,
|
|
77
|
+
unheardReviewers,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Process for handling disagreement within the circle.
|
|
82
|
+
* Returns guidance for resolution based on the process type.
|
|
83
|
+
*/
|
|
84
|
+
function resolveDisagreement(circle, process) {
|
|
85
|
+
switch (process) {
|
|
86
|
+
case 'deeper-listening':
|
|
87
|
+
return {
|
|
88
|
+
guidance: 'Return to the talking circle with renewed attention. Each voice deserves to be fully heard.',
|
|
89
|
+
nextStatus: 'reviewing',
|
|
90
|
+
suggestedActions: [
|
|
91
|
+
'Invite unheard reviewers to speak',
|
|
92
|
+
'Ask clarifying questions without judgment',
|
|
93
|
+
'Reflect back what has been heard',
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
case 'elder-mediation':
|
|
97
|
+
return {
|
|
98
|
+
guidance: 'Request Elder guidance to help the circle find its way forward.',
|
|
99
|
+
nextStatus: 'deliberating',
|
|
100
|
+
suggestedActions: [
|
|
101
|
+
'Request Elder validation if not already assigned',
|
|
102
|
+
'Share the points of tension with the Elder',
|
|
103
|
+
'Allow the Elder to guide the process',
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
case 'return-to-ceremony':
|
|
107
|
+
return {
|
|
108
|
+
guidance: 'The disagreement may require ceremonial attention before resolution is possible.',
|
|
109
|
+
nextStatus: 'reviewing',
|
|
110
|
+
suggestedActions: [
|
|
111
|
+
'Conduct a smudging ceremony',
|
|
112
|
+
'Reground in the Four Directions',
|
|
113
|
+
'Check Wilson alignment as a group',
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
case 'rest-and-return':
|
|
117
|
+
return {
|
|
118
|
+
guidance: 'Sometimes wisdom comes through rest. The circle can reconvene when ready.',
|
|
119
|
+
nextStatus: 'reviewing',
|
|
120
|
+
suggestedActions: [
|
|
121
|
+
'Set a date to reconvene',
|
|
122
|
+
'Invite individual reflection',
|
|
123
|
+
'Allow time for the land to speak',
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=consensus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consensus.js","sourceRoot":"","sources":["../src/consensus.ts"],"names":[],"mappings":"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"}
|